Magically import images and more into Gamecraft as blocks
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
6.7KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using Svelto.DataStructures;
  5. using Unity.Mathematics;
  6. using UnityEngine;
  7. using GamecraftModdingAPI.Blocks;
  8. using GamecraftModdingAPI.Commands;
  9. using GamecraftModdingAPI.Utility;
  10. using Newtonsoft.Json;
  11. using Pixi.Common;
  12. namespace Pixi.Robots
  13. {
  14. public class RobotBlueprintProvider : BlueprintProvider
  15. {
  16. public string Name { get; } = "RobotBlueprintProvider";
  17. private Dictionary<string, BlockJsonInfo[]> botprints = null;
  18. private RobotInternetImporter parent;
  19. public RobotBlueprintProvider(RobotInternetImporter rii)
  20. {
  21. parent = rii;
  22. }
  23. public BlockJsonInfo[] Blueprint(string name, BlockJsonInfo root)
  24. {
  25. if (botprints == null)
  26. {
  27. botprints = BlueprintUtility.ParseBlueprintResource("Pixi.blueprints.json");
  28. }
  29. if (!botprints.ContainsKey(root.name) || RobotInternetImporter.CubeSize != 3)
  30. {
  31. if (!parent.textBlockInfo.ContainsKey(name))
  32. {
  33. parent.textBlockInfo[name] = new FasterList<string>();
  34. }
  35. BlockJsonInfo copy = root;
  36. copy.name = "TextBlock";
  37. Logging.MetaLog($"Parsing uint from '{root.name}'");
  38. parent.textBlockInfo[name].Add(root.name + " (" + CubeUtility.CubeIdDescription(uint.Parse(root.name)) + ")");
  39. return new BlockJsonInfo[1] {copy};
  40. }
  41. BlockJsonInfo[] blueprint = botprints[root.name];
  42. BlockJsonInfo[] adjustedBlueprint = new BlockJsonInfo[blueprint.Length];
  43. Quaternion cubeQuaternion = Quaternion.Euler(ConversionUtility.FloatArrayToFloat3(root.rotation));
  44. if (blueprint.Length == 0)
  45. {
  46. Logging.LogWarning($"Found empty blueprint for {root.name} (during '{name}'), is the blueprint correct?");
  47. return new BlockJsonInfo[0];
  48. }
  49. // move blocks to correct position & rotation
  50. float3 defaultCorrectionVec = new float3((float)(0), (float)(CommandRoot.BLOCK_SIZE), (float)(0));
  51. float3 baseRot = new float3(blueprint[0].rotation[0], blueprint[0].rotation[1], blueprint[0].rotation[2]);
  52. float3 baseScale = new float3(blueprint[0].scale[0], blueprint[0].scale[1], blueprint[0].scale[2]);
  53. //Block[] placedBlocks = new Block[blueprint.Length];
  54. bool isBaseScaled = !(blueprint[0].scale[1] > 0f && blueprint[0].scale[1] < 2f);
  55. float3 correctionVec = isBaseScaled ? (float3)(Quaternion.Euler(baseRot) * baseScale / 2) * (float)-CommandRoot.BLOCK_SIZE : -defaultCorrectionVec;
  56. // FIXME scaled base blocks cause the blueprint to be placed in the wrong location (this also could be caused by a bug in DumpVON command)
  57. if (isBaseScaled)
  58. {
  59. Logging.LogWarning($"Found blueprint with scaled base block for {root.name} (during '{name}'), this is not currently supported");
  60. }
  61. float3 rootPos = ConversionUtility.FloatArrayToFloat3(root.position);
  62. for (int i = 0; i < blueprint.Length; i++)
  63. {
  64. BlockColor blueprintBlockColor = ColorSpaceUtility.QuantizeToBlockColor(blueprint[i].color);
  65. float[] physicalColor = blueprintBlockColor.Color == BlockColors.White && blueprintBlockColor.Darkness == 0 ? root.color : blueprint[i].color;
  66. float3 bluePos = ConversionUtility.FloatArrayToFloat3(blueprint[i].position);
  67. float3 blueScale = ConversionUtility.FloatArrayToFloat3(blueprint[i].scale);
  68. float3 blueRot = ConversionUtility.FloatArrayToFloat3(blueprint[i].rotation);
  69. float3 physicalLocation = (float3)(cubeQuaternion * bluePos) + rootPos;// + (blueprintSizeRotated / 2);
  70. //physicalLocation.x += blueprintSize.x / 2;
  71. physicalLocation += (float3)(cubeQuaternion * (correctionVec));
  72. //physicalLocation.y -= (float)(RobotCommands.blockSize * scale / 2);
  73. //float3 physicalScale = (float3)(cubeQuaternion * blueScale); // this actually over-rotates when combined with rotation
  74. float3 physicalScale = blueScale;
  75. float3 physicalRotation = (cubeQuaternion * Quaternion.Euler(blueRot)).eulerAngles;
  76. #if DEBUG
  77. Logging.MetaLog($"Placing blueprint block at {physicalLocation} rot{physicalRotation} scale{physicalScale}");
  78. Logging.MetaLog($"Location math check original:{bluePos} rotated: {(float3)(cubeQuaternion * bluePos)} actualPos: {rootPos} result: {physicalLocation}");
  79. Logging.MetaLog($"Scale math check original:{blueScale} rotation: {(float3)cubeQuaternion.eulerAngles} result: {physicalScale}");
  80. Logging.MetaLog($"Rotation math check original:{blueRot} rotated: {(cubeQuaternion * Quaternion.Euler(blueRot))} result: {physicalRotation}");
  81. #endif
  82. adjustedBlueprint[i] = new BlockJsonInfo
  83. {
  84. color = physicalColor,
  85. name = blueprint[i].name,
  86. position = ConversionUtility.Float3ToFloatArray(physicalLocation),
  87. rotation = ConversionUtility.Float3ToFloatArray(physicalRotation),
  88. scale = ConversionUtility.Float3ToFloatArray(physicalScale)
  89. };
  90. }
  91. return adjustedBlueprint;
  92. }
  93. #if DEBUG
  94. public void AddDebugCommands()
  95. {
  96. CommandBuilder.Builder("PixiReload", "Reloads the robot blueprints")
  97. .Action(() => botprints = null).Build();
  98. CommandBuilder.Builder("RotateBlueprint",
  99. "Rotates a blueprint with a given ID and dumps the result to a file. 1 means 90 degrees.")
  100. .Action<string>(RotateBlueprint).Build();
  101. }
  102. private void RotateBlueprint(string parameters)
  103. {
  104. var p = parameters.Split(' ');
  105. string id = p[0];
  106. var xyz = new int[3];
  107. for (int i = 0; i < xyz.Length; i++)
  108. xyz[i] = int.Parse(p[i + 1]) * 90;
  109. if (botprints == null)
  110. {
  111. botprints = BlueprintUtility.ParseBlueprintResource("Pixi.blueprints.json");
  112. }
  113. if (!botprints.ContainsKey(id))
  114. {
  115. Logging.CommandLogWarning("Blueprint with that ID not found.");
  116. return;
  117. }
  118. var bp = botprints[id];
  119. var rotChange = Quaternion.Euler(xyz[0], xyz[1], xyz[2]);
  120. for (var i = 0; i < bp.Length; i++)
  121. {
  122. ref var info = ref bp[i];
  123. var pos = ConversionUtility.FloatArrayToFloat3(info.position);
  124. info.position = ConversionUtility.Float3ToFloatArray(rotChange * pos);
  125. var rot = Quaternion.Euler(ConversionUtility.FloatArrayToFloat3(info.rotation));
  126. info.rotation = ConversionUtility.Float3ToFloatArray((rotChange * rot).eulerAngles);
  127. }
  128. File.WriteAllText(id, JsonConvert.SerializeObject(bp));
  129. Logging.CommandLog("Blueprint rotated " + rotChange.eulerAngles + " and dumped");
  130. }
  131. #endif
  132. }
  133. }