private void RotateBlueprint(string parameters) { var p = parameters.Split(' '); string id = p[0]; var xyz = new int[3]; for (int i = 0; i < xyz.Length; i++) { xyz[i] = int.Parse(p[i + 1]) * 90; } if (botprints == null) { botprints = BlueprintUtility.ParseBlueprintResource("Pixi.blueprints.json"); } if (!botprints.ContainsKey(id)) { Logging.CommandLogWarning("Blueprint with that ID not found."); return; } var bp = botprints[id]; var rotChange = Quaternion.Euler(xyz[0], xyz[1], xyz[2]); for (var i = 0; i < bp.Length; i++) { ref var info = ref bp[i]; var pos = ConversionUtility.FloatArrayToFloat3(info.position); info.position = ConversionUtility.Float3ToFloatArray(rotChange * pos); var rot = Quaternion.Euler(ConversionUtility.FloatArrayToFloat3(info.rotation)); info.rotation = ConversionUtility.Float3ToFloatArray((rotChange * rot).eulerAngles); }
public BlockJsonInfo[] Import(string name) { // Load image file and convert to Gamecraft blocks Texture2D img = new Texture2D(64, 64); // load file into texture try { byte[] imgData = File.ReadAllBytes(name); img.LoadImage(imgData); } catch (Exception e) { Logging.CommandLogError($"Failed to load picture data. Reason: {e.Message}"); Logging.MetaLog(e.Message + "\n" + e.StackTrace); return(new BlockJsonInfo[0]); } //Logging.CommandLog($"Image size: {img.width}x{img.height}"); Player p = new Player(PlayerType.Local); string pickedBlock = p.SelectedBlock == BlockIDs.Invalid ? BlockIDs.AluminiumCube.ToString() : p.SelectedBlock.ToString(); Quaternion imgRotation = Quaternion.Euler(Rotation); BlockJsonInfo[] blocks = new BlockJsonInfo[img.width * img.height]; // convert the image to blocks // optimisation occurs later for (int x = 0; x < img.width; x++) { for (int y = 0; y < img.height; y++) { Color pixel = img.GetPixel(x, y); float3 position = (imgRotation * (new float3((x * CommandRoot.BLOCK_SIZE), y * CommandRoot.BLOCK_SIZE, 0))); BlockJsonInfo qPixel = new BlockJsonInfo { name = pixel.a > 0.75 ? pickedBlock : BlockIDs.GlassCube.ToString(), color = new float[] { pixel.r, pixel.g, pixel.b }, rotation = ConversionUtility.Float3ToFloatArray(Rotation), position = ConversionUtility.Float3ToFloatArray(position), scale = new float[] { 1, 1, Thiccness }, }; if (pixel.a < 0.5f) { qPixel.name = BlockIDs.Invalid.ToString(); } blocks[(x * img.height) + y] = qPixel; } } return(blocks); }
public BlockJsonInfo[] Blueprint(string name, BlockJsonInfo root) { if (botprints == null) { botprints = BlueprintUtility.ParseBlueprintResource("Pixi.blueprints.json"); } if (!botprints.ContainsKey(root.name) || RobotInternetImporter.CubeSize != 3) { BlockJsonInfo copy = root; copy.name = $"TextBlock\t{root.name} ({CubeUtility.CubeIdDescription(uint.Parse(root.name))})\tPixi"; return(new BlockJsonInfo[1] { copy }); } BlockJsonInfo[] blueprint = botprints[root.name]; BlockJsonInfo[] adjustedBlueprint = new BlockJsonInfo[blueprint.Length]; Quaternion cubeQuaternion = Quaternion.Euler(ConversionUtility.FloatArrayToFloat3(root.rotation)); if (blueprint.Length == 0) { Logging.LogWarning($"Found empty blueprint for {root.name} (during '{name}'), is the blueprint correct?"); return(new BlockJsonInfo[0]); } // move blocks to correct position & rotation float3 defaultCorrectionVec = new float3((float)(0), (float)(CommandRoot.BLOCK_SIZE), (float)(0)); float3 baseRot = new float3(blueprint[0].rotation[0], blueprint[0].rotation[1], blueprint[0].rotation[2]); float3 baseScale = new float3(blueprint[0].scale[0], blueprint[0].scale[1], blueprint[0].scale[2]); //Block[] placedBlocks = new Block[blueprint.Length]; bool isBaseScaled = !(blueprint[0].scale[1] > 0f && blueprint[0].scale[1] < 2f); float3 correctionVec = isBaseScaled ? (float3)(Quaternion.Euler(baseRot) * baseScale / 2) * (float)-CommandRoot.BLOCK_SIZE : -defaultCorrectionVec; // 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) if (isBaseScaled) { Logging.LogWarning($"Found blueprint with scaled base block for {root.name} (during '{name}'), this is not currently supported"); } float3 rootPos = ConversionUtility.FloatArrayToFloat3(root.position); for (int i = 0; i < blueprint.Length; i++) { BlockColor blueprintBlockColor = ColorSpaceUtility.QuantizeToBlockColor(blueprint[i].color); float[] physicalColor = blueprintBlockColor.Color == BlockColors.White && blueprintBlockColor.Darkness == 0 ? root.color : blueprint[i].color; float3 bluePos = ConversionUtility.FloatArrayToFloat3(blueprint[i].position); float3 blueScale = ConversionUtility.FloatArrayToFloat3(blueprint[i].scale); float3 blueRot = ConversionUtility.FloatArrayToFloat3(blueprint[i].rotation); float3 physicalLocation = (float3)(cubeQuaternion * bluePos) + rootPos; // + (blueprintSizeRotated / 2); //physicalLocation.x += blueprintSize.x / 2; physicalLocation += (float3)(cubeQuaternion * (correctionVec)); //physicalLocation.y -= (float)(RobotCommands.blockSize * scale / 2); //float3 physicalScale = (float3)(cubeQuaternion * blueScale); // this actually over-rotates when combined with rotation float3 physicalScale = blueScale; float3 physicalRotation = (cubeQuaternion * Quaternion.Euler(blueRot)).eulerAngles; #if DEBUG Logging.MetaLog($"Placing blueprint block at {physicalLocation} rot{physicalRotation} scale{physicalScale}"); Logging.MetaLog($"Location math check original:{bluePos} rotated: {(float3)(cubeQuaternion * bluePos)} actualPos: {rootPos} result: {physicalLocation}"); Logging.MetaLog($"Scale math check original:{blueScale} rotation: {(float3)cubeQuaternion.eulerAngles} result: {physicalScale}"); Logging.MetaLog($"Rotation math check original:{blueRot} rotated: {(cubeQuaternion * Quaternion.Euler(blueRot))} result: {physicalRotation}"); #endif adjustedBlueprint[i] = new BlockJsonInfo { color = physicalColor, name = blueprint[i].name, position = ConversionUtility.Float3ToFloatArray(physicalLocation), rotation = ConversionUtility.Float3ToFloatArray(physicalRotation), scale = ConversionUtility.Float3ToFloatArray(physicalScale) }; } return(adjustedBlueprint); }
public BlockJsonInfo[] Import(string name) { // download robot data RobotStruct robot; try { RobotBriefStruct[] botList = RoboAPIUtility.ListRobots(name); if (botList.Length == 0) { throw new Exception("Failed to find robot"); } robot = RoboAPIUtility.QueryRobotInfo(botList[0].itemId); } catch (Exception e) { Logging.CommandLogError($"Failed to download robot data. Reason: {e.Message}"); Logging.MetaLog(e); return(new BlockJsonInfo[0]); } CubeInfo[] cubes = CubeUtility.ParseCubes(robot); // move bot closer to origin (since bots are rarely built at the garage bay origin of the bottom south-west corner) if (cubes.Length == 0) { Logging.CommandLogError($"Robot data contains no cubes"); return(new BlockJsonInfo[0]); } float3 minPosition = cubes[0].position; for (int c = 0; c < cubes.Length; c++) { float3 cubePos = cubes[c].position; if (cubePos.x < minPosition.x) { minPosition.x = cubePos.x; } if (cubePos.y < minPosition.y) { minPosition.y = cubePos.y; } if (cubePos.z < minPosition.z) { minPosition.z = cubePos.z; } } BlockJsonInfo[] blocks = new BlockJsonInfo[cubes.Length]; for (int c = 0; c < cubes.Length; c++) { ref CubeInfo cube = ref cubes[c]; float3 realPosition = ((cube.position - minPosition) * CommandRoot.BLOCK_SIZE * CubeSize); if (cube.block == BlockIDs.TextBlock && !string.IsNullOrEmpty(cube.name)) { // TextBlock block ID means it's a placeholder blocks[c] = new BlockJsonInfo { color = ColorSpaceUtility.UnquantizeToArray(cube.color, cube.darkness), name = cube.cubeId.ToString(), position = ConversionUtility.Float3ToFloatArray(realPosition), rotation = ConversionUtility.Float3ToFloatArray(cube.rotation), scale = ConversionUtility.Float3ToFloatArray(cube.scale) }; } else { blocks[c] = new BlockJsonInfo { color = ColorSpaceUtility.UnquantizeToArray(cube.color, cube.darkness), name = cube.block.ToString(), position = ConversionUtility.Float3ToFloatArray(realPosition), rotation = ConversionUtility.Float3ToFloatArray(cube.rotation), scale = ConversionUtility.Float3ToFloatArray(cube.scale * CubeSize) }; } }