/// <summary> /// Uses the VisualServer to draw each of an entity's split sprites, by: /// 1. Obtaining the Node2D that is designated to play host to a given split sprite /// 2. Changing the Node2D's (TileMap) parent if required /// 3. Creating an RID for the canvas item (the sprite drawing) and storing it so it can be freed later /// </summary> /// <param name="tileMaps"></param> /// <param name="tileMapZIndex"></param> /// <param name="entityPos"></param> /// <param name="entityDrawPos">Offsets the sprite upwards. Used for drawing entities falling/jumping.</param> public void DrawSplitSprites(TileMapList tileMaps, int tileMapZIndex, Vector2 entityPos, float entityDrawPos /*State goes here*/) { List <SplitSpriteSheetValue> splitSprites = this._splitSpriteSheet.GetSplitSpriteInfoForAnim("idle", 0); //TODO match to entity anim state foreach (SplitSpriteSheetValue splitSprite in splitSprites) { Node2D splitNode2D = this._idToSplitNodes[splitSprite.splitIndex]; TileMap tileMap = tileMaps[tileMapZIndex + splitSprite.zIndex]; if (splitNode2D.GetParent() != tileMap) { if (splitNode2D.GetParent() != null) { splitNode2D.GetParent().RemoveChild(splitNode2D); } tileMap.AddChild(splitNode2D); } RID splitSpriteRID = VisualServer.CanvasItemCreate(); this._drawnSprites.Add(splitSpriteRID); VisualServer.CanvasItemSetParent(splitSpriteRID, splitNode2D.GetCanvasItem()); VisualServer.CanvasItemAddTextureRectRegion(splitSpriteRID, new Rect2(Vector2.Zero, splitSprite.size), this._splitSpriteSheet.GetSpriteSheetRID(), new Rect2(splitSprite.sheetPos, splitSprite.size), new Color(1, 1, 1, 1), false, this._splitSpriteSheet.GetSpriteSheetRID()); VisualServer.CanvasItemSetTransform(splitSpriteRID, new Transform2D(0, this._relativePos - new Vector2(Globals.TileWidth / 2, Globals.TileHeight / 2) + new Vector2(0, entityDrawPos))); splitNode2D.Position = entityPos + splitSprite.splitPos + new Vector2(Globals.TileWidth / 2, Globals.TileHeight / 2); } }
private static void RenderDrawData(ImDrawDataPtr drawData, RID parent) { // allocate and clear out our CanvasItem pool as needed int neededNodes = 0; for (int i = 0; i < drawData.CmdListsCount; i++) { neededNodes += drawData.CmdListsRange[i].CmdBuffer.Size; } while (_children.Count < neededNodes) { RID newChild = VisualServer.CanvasItemCreate(); VisualServer.CanvasItemSetParent(newChild, parent); VisualServer.CanvasItemSetDrawIndex(newChild, _children.Count); _children.Add(newChild); _meshes.Add(new ArrayMesh()); } // trim unused nodes to reduce draw calls while (_children.Count > neededNodes) { int idx = _children.Count - 1; VisualServer.FreeRid(_children[idx]); _children.RemoveAt(idx); _meshes.RemoveAt(idx); } // render drawData.ScaleClipRects(ImGui.GetIO().DisplayFramebufferScale); int nodeN = 0; for (int n = 0; n < drawData.CmdListsCount; n++) { ImDrawListPtr cmdList = drawData.CmdListsRange[n]; int idxOffset = 0; int nVert = cmdList.VtxBuffer.Size; Godot.Vector2[] vertices = new Godot.Vector2[nVert]; Godot.Color[] colors = new Godot.Color[nVert]; Godot.Vector2[] uvs = new Godot.Vector2[nVert]; for (int i = 0; i < cmdList.VtxBuffer.Size; i++) { var v = cmdList.VtxBuffer[i]; vertices[i] = new Godot.Vector2(v.pos.X, v.pos.Y); // need to reverse the color bytes byte[] col = BitConverter.GetBytes(v.col); colors[i] = Godot.Color.Color8(col[0], col[1], col[2], col[3]); uvs[i] = new Godot.Vector2(v.uv.X, v.uv.Y); } for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++, nodeN++) { ImDrawCmdPtr drawCmd = cmdList.CmdBuffer[cmdi]; int[] indices = new int[drawCmd.ElemCount]; for (int i = idxOffset, j = 0; i < idxOffset + drawCmd.ElemCount; i++, j++) { indices[j] = cmdList.IdxBuffer[i]; } var arrays = new Godot.Collections.Array(); arrays.Resize((int)ArrayMesh.ArrayType.Max); arrays[(int)ArrayMesh.ArrayType.Vertex] = vertices; arrays[(int)ArrayMesh.ArrayType.Color] = colors; arrays[(int)ArrayMesh.ArrayType.TexUv] = uvs; arrays[(int)ArrayMesh.ArrayType.Index] = indices; var mesh = _meshes[nodeN]; while (mesh.GetSurfaceCount() > 0) { mesh.SurfaceRemove(0); } mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays); RID child = _children[nodeN]; Texture tex = GetTexture(drawCmd.TextureId); VisualServer.CanvasItemClear(child); VisualServer.CanvasItemSetClip(child, true); VisualServer.CanvasItemSetCustomRect(child, true, new Godot.Rect2( drawCmd.ClipRect.X, drawCmd.ClipRect.Y, drawCmd.ClipRect.Z - drawCmd.ClipRect.X, drawCmd.ClipRect.W - drawCmd.ClipRect.Y) ); VisualServer.CanvasItemAddMesh(child, mesh.GetRid(), null, null, tex.GetRid(), new RID(null)); // why doesn't this quite work? // VisualServer.CanvasItemAddTriangleArray(child, indices, vertices, colors, uvs, null, null, tex.GetRid(), -1, new RID(null)); idxOffset += (int)drawCmd.ElemCount; } } }