Decompiled source of ShoppingList v0.2.0
BepInEx/plugins/ShoppingList.dll
Decompiled 3 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Logging; using HarmonyLib; using KaimiraGames; using Microsoft.CodeAnalysis; using StbRectPackSharp; using Unity.Netcode; using Unity.VisualScripting; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("ShoppingList")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("Shopping List")] [assembly: AssemblyTitle("ShoppingList")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace KaimiraGames { public class WeightedList<T> : IEnumerable<T>, IEnumerable { private readonly List<T> _list = new List<T>(); private readonly List<int> _weights = new List<int>(); private readonly List<int> _probabilities = new List<int>(); private readonly List<int> _alias = new List<int>(); private readonly Random _rand; private int _totalWeight; private bool _areAllProbabilitiesIdentical = false; private int _minWeight; private int _maxWeight; public WeightErrorHandlingType BadWeightErrorHandling { get; set; } = WeightErrorHandlingType.SetWeightToOne; public int TotalWeight => _totalWeight; public int MinWeight => _minWeight; public int MaxWeight => _maxWeight; public IReadOnlyList<T> Items => _list.AsReadOnly(); public T this[int index] => _list[index]; public int Count => _list.Count; public WeightedList(Random rand = null) { _rand = rand ?? new Random(); } public WeightedList(ICollection<WeightedListItem<T>> listItems, Random rand = null) { _rand = rand ?? new Random(); foreach (WeightedListItem<T> listItem in listItems) { _list.Add(listItem._item); _weights.Add(listItem._weight); } Recalculate(); } public T Next() { if (Count == 0) { return default(T); } int index = _rand.Next(Count); if (_areAllProbabilitiesIdentical) { return _list[index]; } int num = _rand.Next(_totalWeight); return (num < _probabilities[index]) ? _list[index] : _list[_alias[index]]; } public void AddWeightToAll(int weight) { if (weight + _minWeight <= 0 && BadWeightErrorHandling == WeightErrorHandlingType.ThrowExceptionOnAdd) { throw new ArgumentException($"Subtracting {-1 * weight} from all items would set weight to non-positive for at least one element."); } for (int i = 0; i < Count; i++) { _weights[i] = FixWeight(_weights[i] + weight); } Recalculate(); } public void SubtractWeightFromAll(int weight) { AddWeightToAll(weight * -1); } public void SetWeightOfAll(int weight) { if (weight <= 0 && BadWeightErrorHandling == WeightErrorHandlingType.ThrowExceptionOnAdd) { throw new ArgumentException("Weight cannot be non-positive."); } for (int i = 0; i < Count; i++) { _weights[i] = FixWeight(weight); } Recalculate(); } public IEnumerator<T> GetEnumerator() { return _list.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return _list.GetEnumerator(); } public void Add(T item, int weight) { _list.Add(item); _weights.Add(FixWeight(weight)); Recalculate(); } public void Add(ICollection<WeightedListItem<T>> listItems) { foreach (WeightedListItem<T> listItem in listItems) { _list.Add(listItem._item); _weights.Add(FixWeight(listItem._weight)); } Recalculate(); } public void Clear() { _list.Clear(); _weights.Clear(); Recalculate(); } public bool Contains(T item) { return _list.Contains(item); } public int IndexOf(T item) { return _list.IndexOf(item); } public void Insert(int index, T item, int weight) { _list.Insert(index, item); _weights.Insert(index, FixWeight(weight)); Recalculate(); } public void Remove(T item) { int index = IndexOf(item); RemoveAt(index); Recalculate(); } public void RemoveAt(int index) { _list.RemoveAt(index); _weights.RemoveAt(index); Recalculate(); } public void SetWeight(T item, int newWeight) { SetWeightAtIndex(IndexOf(item), FixWeight(newWeight)); } public int GetWeightOf(T item) { return GetWeightAtIndex(IndexOf(item)); } public void SetWeightAtIndex(int index, int newWeight) { _weights[index] = FixWeight(newWeight); Recalculate(); } public int GetWeightAtIndex(int index) { return _weights[index]; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("WeightedList<"); stringBuilder.Append(typeof(T).Name); stringBuilder.Append(">: TotalWeight:"); stringBuilder.Append(TotalWeight); stringBuilder.Append(", Min:"); stringBuilder.Append(_minWeight); stringBuilder.Append(", Max:"); stringBuilder.Append(_maxWeight); stringBuilder.Append(", Count:"); stringBuilder.Append(Count); stringBuilder.Append(", {"); for (int i = 0; i < _list.Count; i++) { stringBuilder.Append(_list[i].ToString()); stringBuilder.Append(":"); stringBuilder.Append(_weights[i].ToString()); if (i < _list.Count - 1) { stringBuilder.Append(", "); } } stringBuilder.Append("}"); return stringBuilder.ToString(); } private void Recalculate() { _totalWeight = 0; _areAllProbabilitiesIdentical = false; _minWeight = 0; _maxWeight = 0; bool flag = true; _alias.Clear(); _probabilities.Clear(); List<int> list = new List<int>(Count); List<int> list2 = new List<int>(Count); List<int> list3 = new List<int>(Count); foreach (int weight in _weights) { if (flag) { _minWeight = (_maxWeight = weight); flag = false; } _minWeight = ((weight < _minWeight) ? weight : _minWeight); _maxWeight = ((_maxWeight < weight) ? weight : _maxWeight); _totalWeight += weight; list.Add(weight * Count); _alias.Add(0); _probabilities.Add(0); } if (_minWeight == _maxWeight) { _areAllProbabilitiesIdentical = true; return; } for (int i = 0; i < Count; i++) { if (list[i] < _totalWeight) { list2.Add(i); } else { list3.Add(i); } } while (list2.Count > 0 && list3.Count > 0) { int index = list2[list2.Count - 1]; list2.RemoveAt(list2.Count - 1); int num = list3[list3.Count - 1]; list3.RemoveAt(list3.Count - 1); _probabilities[index] = list[index]; _alias[index] = num; int num3 = (list[num] = list[num] + list[index] - _totalWeight); if (num3 < _totalWeight) { list2.Add(num); } else { list3.Add(num); } } while (list3.Count > 0) { int index2 = list3[list3.Count - 1]; list3.RemoveAt(list3.Count - 1); _probabilities[index2] = _totalWeight; } } internal static int FixWeightSetToOne(int weight) { return (weight <= 0) ? 1 : weight; } internal static int FixWeightExceptionOnAdd(int weight) { if (weight > 0) { return weight; } throw new ArgumentException("Weight cannot be non-positive"); } private int FixWeight(int weight) { return (BadWeightErrorHandling == WeightErrorHandlingType.ThrowExceptionOnAdd) ? FixWeightExceptionOnAdd(weight) : FixWeightSetToOne(weight); } } public readonly struct WeightedListItem<T> { internal readonly T _item; internal readonly int _weight; public WeightedListItem(T item, int weight) { _item = item; _weight = weight; } } public enum WeightErrorHandlingType { SetWeightToOne, ThrowExceptionOnAdd } } namespace System.Runtime.CompilerServices { public class ExtensionAttribute : Attribute { } } namespace ShoppingList { [BepInPlugin("yasenfire.shoppinglist", "ShoppingList", "0.1.0")] public class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(CustomerController), "SetupShoppingList")] private class SetupShoppingListPatch { private static bool Prefix(CustomerController __instance) { __instance.shoppingList.Clear(); List<ProductSO> list = GameManager.Instance.itemDatabase.Where((ItemSO x) => x is ProductSO).Cast<ProductSO>().ToList(); List<WeightedListItem<ProductSO>> list2 = new List<WeightedListItem<ProductSO>>(); SeasonSO currentSeason = GameManager.Instance.GetCurrentSeason(); EventSO currentEvent = GameManager.Instance.GetCurrentEvent(); foreach (ProductSO item2 in list) { float num = 100f; num = ((!((Object)(object)currentSeason == (Object)(object)item2.season)) ? (num * 0.9f) : (num * 1.2f)); float num2 = GameManager.Instance.GetSellingPriceServer(item2); float num3 = GameManager.Instance.GetRecommendedPrice(item2); float num4 = num3 / num2; num = ((!(num4 > 1f)) ? (num * Mathf.Lerp(0.1f, 1f, (Mathf.Clamp(num4, 0.8f, 1f) - 0.8f) * 10f)) : (num * Mathf.Lerp(1f, 8f, Mathf.Clamp(num4, 1f, 2f) - 1f))); num *= Random.Range(0.8f, 1.2f); if (currentEvent != null) { if (currentEvent.forbiddenProducts.Contains(item2)) { num *= 0.1f; } if (currentEvent.products.Contains(item2)) { num *= Random.Range(2f, 4f); } } list2.Add(new WeightedListItem<ProductSO>(item2, Mathf.RoundToInt(num))); } WeightedList<ProductSO> weightedList = new WeightedList<ProductSO>(list2); List<ProductSO> list3 = (from x in LinqUtility.DistinctBy<Item, long>(from x in Object.FindObjectsOfType<Item>() where x.itemSO is ProductSO && x.onStand.Value && x.amount.Value > 0 select x, (Func<Item, long>)((Item x) => x.itemSO.id)) select x.itemSO).Cast<ProductSO>().ToList(); float num5 = (float)list3.Count / (float)list.Count; string text = weightedBuyerList.Next(); if (text == "obsessive") { ProductSO val = weightedList.Next(); int num6 = Random.Range(4, Mathf.Min(((ItemSO)val).amount, 24)); for (int i = 0; i < num6; i++) { __instance.shoppingList.Add(val); } return false; } if (text == "loyal") { int num7 = Mathf.RoundToInt(Mathf.Lerp(0f, 18f, num5)) + 6; int num8 = Random.Range(1, num7); for (int j = 0; j < num8; j++) { ProductSO item; do { item = weightedList.Next(); } while (!list3.Contains(item)); __instance.shoppingList.Add(item); } return false; } int num9 = Random.Range(1, 24); int num10 = 0; List<ProductSO> list4 = new List<ProductSO>(); for (int k = 0; k < num9; k++) { ProductSO val2 = weightedList.Next(); list4.Add(val2); int num11 = 1; for (; k < num9; k++) { if (!(Random.Range(0f, 1f) < (float)(((ItemSO)val2).amount / 100 / num11))) { break; } list4.Add(val2); num11++; } if (list3.Contains(val2)) { num10 += num11; } } if ((float)(num10 / num9) >= 0.5f) { for (int l = 0; l < list4.Count; l++) { if (list3.Contains(list4[l])) { __instance.shoppingList.Add(list4[l]); } } } return false; } } [HarmonyPatch(typeof(Checkout), "SpawnProducts")] private class CheckoutSpawnProductsPatch { private static bool Prefix(Checkout __instance) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) if (__instance.spawnedProducts) { return false; } object value = Traverse.Create((object)__instance).Field("checkoutEmployee").GetValue(); CheckoutEmployee val = (CheckoutEmployee)((value is CheckoutEmployee) ? value : null); List<CustomerController> list = Traverse.Create((object)__instance).Field("customers").GetValue() as List<CustomerController>; Transform child = __instance.productSlots.GetChild(0); Transform child2 = __instance.productSlots.GetChild(8); float num = Mathf.Abs(child2.localPosition.x * 1000f - child.localPosition.x * 1000f); float num2 = Mathf.Abs(child2.localPosition.z * 1000f - child.localPosition.z * 1000f) * 2f; List<ProductSO> shoppingCart = list[0].shoppingCart; shoppingCart.Sort((ProductSO x, ProductSO y) => ((ItemSO)x).id.CompareTo(((ItemSO)y).id)); Packer val2 = new Packer(Mathf.RoundToInt(num), Mathf.RoundToInt(num2)); for (int i = 0; i < shoppingCart.Count; i++) { Transform child3 = __instance.productSlots.GetChild(0); ProductSO val3 = shoppingCart[i]; GameObject item = Object.Instantiate<GameObject>(GameManager.Instance.checkoutItem, child3.position, child3.rotation); Mesh sharedMesh = val3.pickupPrefab.GetComponentsInChildren<MeshFilter>()[0].sharedMesh; Bounds bounds = sharedMesh.bounds; Vector3 size = ((Bounds)(ref bounds)).size; val2.PackRect(Mathf.RoundToInt(size.z * 1000f * val3.pickupPrefab.transform.localScale.z), Mathf.RoundToInt(size.x * 1000f * val3.pickupPrefab.transform.localScale.x), (object)(item, ((ItemSO)val3).id)); } foreach (PackerRectangle packRectangle in val2.PackRectangles) { (GameObject, long) obj = ((GameObject, long))packRectangle.Data; GameObject item2 = obj.Item1; long item3 = obj.Item2; NetworkObject component = item2.GetComponent<NetworkObject>(); component.Spawn(false); ((Component)component).GetComponent<CheckoutItem>().ServerSetupItem(item3, __instance); component.TrySetParent(((Component)__instance).gameObject.transform, true); Transform transform = item2.transform; transform.localPosition += new Vector3((float)packRectangle.Rectangle.Y / 1000f, 0f, (float)packRectangle.Rectangle.X / 1000f * -1f); } __instance.spawnedProducts = true; if ((Object)(object)val != (Object)null) { val.Work(); } return false; } } internal static ManualLogSource Logger; private Harmony m_harmony = new Harmony("yasenfire.shoppinglist"); public static WeightedList<string> weightedBuyerList; private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Plugin ShoppingList is loaded!"); m_harmony.PatchAll(); List<WeightedListItem<string>> listItems = new List<WeightedListItem<string>> { new WeightedListItem<string>("obsessive", 1), new WeightedListItem<string>("loyal", 20), new WeightedListItem<string>("standard", 79) }; weightedBuyerList = new WeightedList<string>(listItems); } } }
BepInEx/plugins/StbRectPackSharp.dll
Decompiled 3 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: AssemblyCompany("StbRectPackSharpTeam")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("C# port of the stb_rect_pack.h")] [assembly: AssemblyFileVersion("1.0.4.0")] [assembly: AssemblyInformationalVersion("1.00.4")] [assembly: AssemblyProduct("StbRectPackSharp")] [assembly: AssemblyTitle("StbRectPackSharp")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.4.0")] [module: UnverifiableCode] namespace StbRectPackSharp; internal static class CRuntime { public unsafe delegate int QSortComparer(void* a, void* b); public unsafe static void* malloc(ulong size) { return malloc((long)size); } public unsafe static void* malloc(long size) { return Marshal.AllocHGlobal((int)size).ToPointer(); } public unsafe static void free(void* a) { Marshal.FreeHGlobal(new IntPtr(a)); } private unsafe static void qsortSwap(byte* data, long size, long pos1, long pos2) { byte* ptr = data + size * pos1; byte* ptr2 = data + size * pos2; for (long num = 0L; num < size; num++) { byte b = *ptr; *ptr = *ptr2; *ptr2 = b; ptr++; ptr2++; } } private unsafe static long qsortPartition(byte* data, long size, QSortComparer comparer, long left, long right) { void* b = data + size * left; long num = left - 1; long num2 = right + 1; while (true) { num++; if (comparer(data + size * num, b) >= 0) { do { num2--; } while (comparer(data + size * num2, b) > 0); if (num >= num2) { break; } qsortSwap(data, size, num, num2); } } return num2; } private unsafe static void qsortInternal(byte* data, long size, QSortComparer comparer, long left, long right) { if (left < right) { long num = qsortPartition(data, size, comparer, left, right); qsortInternal(data, size, comparer, left, num); qsortInternal(data, size, comparer, num + 1, right); } } public unsafe static void qsort(void* data, ulong count, ulong size, QSortComparer comparer) { qsortInternal((byte*)data, (long)size, comparer, 0L, (long)(count - 1)); } } public class PackerRectangle { public Rectangle Rectangle { get; private set; } public int X => Rectangle.X; public int Y => Rectangle.Y; public int Width => Rectangle.Width; public int Height => Rectangle.Height; public object Data { get; private set; } public PackerRectangle(Rectangle rect, object data) { Rectangle = rect; Data = data; } } public class Packer : IDisposable { private StbRectPack.stbrp_context _context; private List<PackerRectangle> _rectangles = new List<PackerRectangle>(); public int Width => _context.width; public int Height => _context.height; public List<PackerRectangle> PackRectangles => _rectangles; public Packer(int initialWidth = 256, int initialHeight = 256) { InitContext(initialWidth, initialHeight); } public void Dispose() { _context.Dispose(); } private unsafe void InitContext(int width, int height) { if (width <= 0) { throw new ArgumentOutOfRangeException("width"); } if (height <= 0) { throw new ArgumentOutOfRangeException("height"); } _context.Dispose(); StbRectPack.stbrp_context context = new StbRectPack.stbrp_context(width); StbRectPack.stbrp_init_target(&context, width, height, context.all_nodes, width); _context = context; _rectangles = new List<PackerRectangle>(); } public unsafe PackerRectangle PackRect(int width, int height, object userData) { StbRectPack.stbrp_rect stbrp_rect = default(StbRectPack.stbrp_rect); stbrp_rect.id = _rectangles.Count; stbrp_rect.w = width; stbrp_rect.h = height; StbRectPack.stbrp_rect stbrp_rect2 = stbrp_rect; int num; fixed (StbRectPack.stbrp_context* context = &_context) { num = StbRectPack.stbrp_pack_rects(context, &stbrp_rect2, 1); } if (num == 0) { return null; } PackerRectangle packerRectangle = new PackerRectangle(new Rectangle(stbrp_rect2.x, stbrp_rect2.y, stbrp_rect2.w, stbrp_rect2.h), userData); _rectangles.Add(packerRectangle); return packerRectangle; } } public static class StbRectPack { public struct stbrp_context : IDisposable { public int width; public int height; public int align; public int init_mode; public int heuristic; public int num_nodes; public unsafe stbrp_node* active_head; public unsafe stbrp_node* free_head; public unsafe stbrp_node* extra; public unsafe stbrp_node* all_nodes; public unsafe stbrp_context(int nodesCount) { if (nodesCount <= 0) { throw new ArgumentOutOfRangeException("nodesCount"); } width = (height = (align = (init_mode = (heuristic = (num_nodes = 0))))); active_head = (free_head = null); all_nodes = (stbrp_node*)CRuntime.malloc(sizeof(stbrp_node) * nodesCount); extra = (stbrp_node*)CRuntime.malloc(sizeof(stbrp_node) * 2); } public unsafe void Dispose() { if (all_nodes != null) { CRuntime.free(all_nodes); all_nodes = null; } if (extra != null) { CRuntime.free(extra); extra = null; } } } public struct stbrp_rect { public int id; public int w; public int h; public int x; public int y; public int was_packed; } public struct stbrp_node { public int x; public int y; public unsafe stbrp_node* next; } public struct stbrp__findresult { public int x; public int y; public unsafe stbrp_node** prev_link; } public const int STBRP_HEURISTIC_Skyline_default = 0; public const int STBRP_HEURISTIC_Skyline_BL_sortHeight = 0; public const int STBRP_HEURISTIC_Skyline_BF_sortHeight = 2; public const int STBRP__INIT_skyline = 1; public unsafe static void stbrp_setup_heuristic(stbrp_context* context, int heuristic) { if (context->init_mode == 1) { context->heuristic = heuristic; return; } throw new Exception("Mode " + context->init_mode + " is not supported."); } public unsafe static void stbrp_setup_allow_out_of_mem(stbrp_context* context, int allow_out_of_mem) { if (allow_out_of_mem != 0) { context->align = 1; } else { context->align = (context->width + context->num_nodes - 1) / context->num_nodes; } } public unsafe static void stbrp_init_target(stbrp_context* context, int width, int height, stbrp_node* nodes, int num_nodes) { int num = 0; for (num = 0; num < num_nodes - 1; num++) { nodes[num].next = nodes + (num + 1); } nodes[num].next = null; context->init_mode = 1; context->heuristic = 0; context->free_head = nodes; context->active_head = context->extra; context->width = width; context->height = height; context->num_nodes = num_nodes; stbrp_setup_allow_out_of_mem(context, 0); context->extra->x = 0; context->extra->y = 0; context->extra->next = context->extra + 1; context->extra[1].x = width; context->extra[1].y = 65535; context->extra[1].next = null; } public unsafe static int stbrp__skyline_find_min_y(stbrp_context* c, stbrp_node* first, int x0, int width, int* pwaste) { stbrp_node* ptr = first; int num = x0 + width; int num2 = 0; int num3 = 0; int num4 = 0; num2 = 0; num4 = 0; num3 = 0; while (ptr->x < num) { if (ptr->y > num2) { num4 += num3 * (ptr->y - num2); num2 = ptr->y; num3 = ((ptr->x >= x0) ? (num3 + (ptr->next->x - ptr->x)) : (num3 + (ptr->next->x - x0))); } else { int num5 = ptr->next->x - ptr->x; if (num5 + num3 > width) { num5 = width - num3; } num4 += num5 * (num2 - ptr->y); num3 += num5; } ptr = ptr->next; } *pwaste = num4; return num2; } public unsafe static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context* c, int width, int height) { int num = 1073741824; int num2 = 0; int num3 = 1073741824; stbrp__findresult result = default(stbrp__findresult); stbrp_node** ptr = null; width = width + c->align - 1; width -= width % c->align; if (width > c->width || height > c->height) { result.prev_link = null; result.x = (result.y = 0); return result; } stbrp_node* ptr2 = c->active_head; stbrp_node** ptr3 = &c->active_head; while (ptr2->x + width <= c->width) { int num4 = 0; int num5 = 0; num4 = stbrp__skyline_find_min_y(c, ptr2, ptr2->x, width, &num5); if (c->heuristic == 0) { if (num4 < num3) { num3 = num4; ptr = ptr3; } } else if (num4 + height <= c->height && (num4 < num3 || (num4 == num3 && num5 < num))) { num3 = num4; num = num5; ptr = ptr3; } ptr3 = &ptr2->next; ptr2 = ptr2->next; } num2 = ((ptr != null) ? (*ptr)->x : 0); if (c->heuristic == 2) { stbrp_node* ptr4 = c->active_head; ptr2 = c->active_head; ptr3 = &c->active_head; while (ptr4->x < width) { ptr4 = ptr4->next; } while (ptr4 != null) { int num6 = ptr4->x - width; int num7 = 0; int num8 = 0; while (ptr2->next->x <= num6) { ptr3 = &ptr2->next; ptr2 = ptr2->next; } num7 = stbrp__skyline_find_min_y(c, ptr2, num6, width, &num8); if (num7 + height <= c->height && num7 <= num3 && (num7 < num3 || num8 < num || (num8 == num && num6 < num2))) { num2 = num6; num3 = num7; num = num8; ptr = ptr3; } ptr4 = ptr4->next; } } result.prev_link = ptr; result.x = num2; result.y = num3; return result; } public unsafe static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context* context, int width, int height) { stbrp__findresult result = stbrp__skyline_find_best_pos(context, width, height); if (result.prev_link == null || result.y + height > context->height || context->free_head == null) { result.prev_link = null; return result; } stbrp_node* free_head = context->free_head; free_head->x = result.x; free_head->y = result.y + height; context->free_head = free_head->next; stbrp_node* ptr = *result.prev_link; if (ptr->x < result.x) { stbrp_node* next = ptr->next; ptr->next = free_head; ptr = next; } else { *result.prev_link = free_head; } while (ptr->next != null && ptr->next->x <= result.x + width) { stbrp_node* next2 = ptr->next; ptr->next = context->free_head; context->free_head = ptr; ptr = next2; } free_head->next = ptr; if (ptr->x < result.x + width) { ptr->x = result.x + width; } return result; } public unsafe static int rect_height_compare(void* a, void* b) { if (((stbrp_rect*)a)->h > ((stbrp_rect*)b)->h) { return -1; } if (((stbrp_rect*)a)->h < ((stbrp_rect*)b)->h) { return 1; } if (((stbrp_rect*)a)->w <= ((stbrp_rect*)b)->w) { if (((stbrp_rect*)a)->w >= ((stbrp_rect*)b)->w) { return 0; } return 1; } return -1; } public unsafe static int rect_original_order(void* a, void* b) { if (((stbrp_rect*)a)->was_packed >= ((stbrp_rect*)b)->was_packed) { if (((stbrp_rect*)a)->was_packed <= ((stbrp_rect*)b)->was_packed) { return 0; } return 1; } return -1; } public unsafe static int stbrp_pack_rects(stbrp_context* context, stbrp_rect* rects, int num_rects) { int num = 0; int result = 1; for (num = 0; num < num_rects; num++) { rects[num].was_packed = num; } CRuntime.qsort(rects, (ulong)num_rects, (ulong)sizeof(stbrp_rect), rect_height_compare); for (num = 0; num < num_rects; num++) { if (rects[num].w == 0 || rects[num].h == 0) { rects[num].x = (rects[num].y = 0); continue; } stbrp__findresult stbrp__findresult = stbrp__skyline_pack_rectangle(context, rects[num].w, rects[num].h); if (stbrp__findresult.prev_link != null) { rects[num].x = stbrp__findresult.x; rects[num].y = stbrp__findresult.y; } else { rects[num].x = (rects[num].y = 65535); } } CRuntime.qsort(rects, (ulong)num_rects, (ulong)sizeof(stbrp_rect), rect_original_order); for (num = 0; num < num_rects; num++) { rects[num].was_packed = ((rects[num].x != 65535 || rects[num].y != 65535) ? 1 : 0); if (rects[num].was_packed == 0) { result = 0; } } return result; } }