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.

140 lines
6.4KB

  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. BlockJsonInfo copy = root;
  32. copy.name = $"TextBlock\t{root.name} ({CubeUtility.CubeIdDescription(uint.Parse(root.name))})\tPixi";
  33. return new BlockJsonInfo[1] {copy};
  34. }
  35. BlockJsonInfo[] blueprint = botprints[root.name];
  36. BlockJsonInfo[] adjustedBlueprint = new BlockJsonInfo[blueprint.Length];
  37. Quaternion cubeQuaternion = Quaternion.Euler(ConversionUtility.FloatArrayToFloat3(root.rotation));
  38. if (blueprint.Length == 0)
  39. {
  40. Logging.LogWarning($"Found empty blueprint for {root.name} (during '{name}'), is the blueprint correct?");
  41. return new BlockJsonInfo[0];
  42. }
  43. // move blocks to correct position & rotation
  44. float3 defaultCorrectionVec = new float3((float)(0), (float)(CommandRoot.BLOCK_SIZE), (float)(0));
  45. float3 baseRot = new float3(blueprint[0].rotation[0], blueprint[0].rotation[1], blueprint[0].rotation[2]);
  46. float3 baseScale = new float3(blueprint[0].scale[0], blueprint[0].scale[1], blueprint[0].scale[2]);
  47. //Block[] placedBlocks = new Block[blueprint.Length];
  48. bool isBaseScaled = !(blueprint[0].scale[1] > 0f && blueprint[0].scale[1] < 2f);
  49. float3 correctionVec = isBaseScaled ? (float3)(Quaternion.Euler(baseRot) * baseScale / 2) * (float)-CommandRoot.BLOCK_SIZE : -defaultCorrectionVec;
  50. // 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)
  51. if (isBaseScaled)
  52. {
  53. Logging.LogWarning($"Found blueprint with scaled base block for {root.name} (during '{name}'), this is not currently supported");
  54. }
  55. float3 rootPos = ConversionUtility.FloatArrayToFloat3(root.position);
  56. for (int i = 0; i < blueprint.Length; i++)
  57. {
  58. BlockColor blueprintBlockColor = ColorSpaceUtility.QuantizeToBlockColor(blueprint[i].color);
  59. float[] physicalColor = blueprintBlockColor.Color == BlockColors.White && blueprintBlockColor.Darkness == 0 ? root.color : blueprint[i].color;
  60. float3 bluePos = ConversionUtility.FloatArrayToFloat3(blueprint[i].position);
  61. float3 blueScale = ConversionUtility.FloatArrayToFloat3(blueprint[i].scale);
  62. float3 blueRot = ConversionUtility.FloatArrayToFloat3(blueprint[i].rotation);
  63. float3 physicalLocation = (float3)(cubeQuaternion * bluePos) + rootPos;// + (blueprintSizeRotated / 2);
  64. //physicalLocation.x += blueprintSize.x / 2;
  65. physicalLocation += (float3)(cubeQuaternion * (correctionVec));
  66. //physicalLocation.y -= (float)(RobotCommands.blockSize * scale / 2);
  67. //float3 physicalScale = (float3)(cubeQuaternion * blueScale); // this actually over-rotates when combined with rotation
  68. float3 physicalScale = blueScale;
  69. float3 physicalRotation = (cubeQuaternion * Quaternion.Euler(blueRot)).eulerAngles;
  70. #if DEBUG
  71. Logging.MetaLog($"Placing blueprint block at {physicalLocation} rot{physicalRotation} scale{physicalScale}");
  72. Logging.MetaLog($"Location math check original:{bluePos} rotated: {(float3)(cubeQuaternion * bluePos)} actualPos: {rootPos} result: {physicalLocation}");
  73. Logging.MetaLog($"Scale math check original:{blueScale} rotation: {(float3)cubeQuaternion.eulerAngles} result: {physicalScale}");
  74. Logging.MetaLog($"Rotation math check original:{blueRot} rotated: {(cubeQuaternion * Quaternion.Euler(blueRot))} result: {physicalRotation}");
  75. #endif
  76. adjustedBlueprint[i] = new BlockJsonInfo
  77. {
  78. color = physicalColor,
  79. name = blueprint[i].name,
  80. position = ConversionUtility.Float3ToFloatArray(physicalLocation),
  81. rotation = ConversionUtility.Float3ToFloatArray(physicalRotation),
  82. scale = ConversionUtility.Float3ToFloatArray(physicalScale)
  83. };
  84. }
  85. return adjustedBlueprint;
  86. }
  87. #if DEBUG
  88. public void AddDebugCommands()
  89. {
  90. CommandBuilder.Builder("PixiReload", "Reloads the robot blueprints")
  91. .Action(() => botprints = null).Build();
  92. CommandBuilder.Builder("RotateBlueprint",
  93. "Rotates a blueprint with a given ID and dumps the result to a file. 1 means 90 degrees.")
  94. .Action<string>(RotateBlueprint).Build();
  95. }
  96. private void RotateBlueprint(string parameters)
  97. {
  98. var p = parameters.Split(' ');
  99. string id = p[0];
  100. var xyz = new int[3];
  101. for (int i = 0; i < xyz.Length; i++)
  102. xyz[i] = int.Parse(p[i + 1]) * 90;
  103. if (botprints == null)
  104. {
  105. botprints = BlueprintUtility.ParseBlueprintResource("Pixi.blueprints.json");
  106. }
  107. if (!botprints.ContainsKey(id))
  108. {
  109. Logging.CommandLogWarning("Blueprint with that ID not found.");
  110. return;
  111. }
  112. var bp = botprints[id];
  113. var rotChange = Quaternion.Euler(xyz[0], xyz[1], xyz[2]);
  114. for (var i = 0; i < bp.Length; i++)
  115. {
  116. ref var info = ref bp[i];
  117. var pos = ConversionUtility.FloatArrayToFloat3(info.position);
  118. info.position = ConversionUtility.Float3ToFloatArray(rotChange * pos);
  119. var rot = Quaternion.Euler(ConversionUtility.FloatArrayToFloat3(info.rotation));
  120. info.rotation = ConversionUtility.Float3ToFloatArray((rotChange * rot).eulerAngles);
  121. }
  122. File.WriteAllText(id, JsonConvert.SerializeObject(bp));
  123. Logging.CommandLog("Blueprint rotated " + rotChange.eulerAngles + " and dumped");
  124. }
  125. #endif
  126. }
  127. }