diff --git a/frontend/src/app/components/block-overview-graph/block-scene.ts b/frontend/src/app/components/block-overview-graph/block-scene.ts index 74a57a8eb..2901f90fd 100644 --- a/frontend/src/app/components/block-overview-graph/block-scene.ts +++ b/frontend/src/app/components/block-overview-graph/block-scene.ts @@ -278,7 +278,7 @@ export default class BlockScene { } private applyTxUpdate(tx: TxView, update: ViewUpdateParams): void { - this.animateUntil = Math.max(this.animateUntil, tx.update(update, { minX: this.x - this.width, maxX: this.x + this.width + this.width, maxY: this.y + this.height })); + this.animateUntil = Math.max(this.animateUntil, tx.update(update, { minX: this.x, maxX: this.x + this.width, minY: this.y, maxY: this.y + this.height })); } private updateTxColor(tx: TxView, startTime: number, delay: number, animate: boolean = true, duration?: number): void { @@ -394,6 +394,7 @@ export default class BlockScene { position: { x: tx.screenPosition.x + (direction === 'right' ? this.width + this.animationOffset : (direction === 'left' ? -this.width - this.animationOffset : 0)), y: tx.screenPosition.y + (direction === 'up' ? this.height + this.animationOffset : (direction === 'down' ? -this.height - this.animationOffset : 0)), + s: tx.screenPosition.s } }, duration: this.animationDuration, @@ -453,7 +454,7 @@ export default class BlockScene { break; } return { - x: this.x + x + this.unitPadding + (slotSize / 2), + x: this.x + x + this.unitPadding - (slotSize / 2), y: this.y + y + this.unitPadding - (slotSize / 2), s: squareSize }; diff --git a/frontend/src/app/components/block-overview-graph/tx-sprite.ts b/frontend/src/app/components/block-overview-graph/tx-sprite.ts index 79525930b..73c3a89a0 100644 --- a/frontend/src/app/components/block-overview-graph/tx-sprite.ts +++ b/frontend/src/app/components/block-overview-graph/tx-sprite.ts @@ -2,12 +2,13 @@ import { FastVertexArray } from './fast-vertex-array'; import { InterpolatedAttribute, Attributes, OptionalAttributes, SpriteUpdateParams, Update } from './sprite-types'; const attribKeys = ['a', 'b', 't', 'v']; -const updateKeys = ['x', 'y', 's', 'r', 'g', 'b', 'a']; +const updateKeys = ['x', 'y', 'r', 'g', 'b', 'a']; +const attributeKeys = ['x', 'y', 's', 'r', 'g', 'b', 'a']; export default class TxSprite { - static vertexSize = 30; + static vertexSize = 28; static vertexCount = 6; - static dataSize: number = (30 * 6); + static dataSize: number = (28 * 6); vertexArray: FastVertexArray; vertexPointer: number; @@ -18,13 +19,14 @@ export default class TxSprite { minX: number; maxX: number; + minY: number; maxY: number; - constructor(params: SpriteUpdateParams, vertexArray: FastVertexArray, minX: number, maxX: number, maxY: number) { + constructor(params: SpriteUpdateParams, vertexArray: FastVertexArray, minX: number, maxX: number, minY: number, maxY: number) { const offsetTime = params.start; this.vertexArray = vertexArray; - this.vertexData = Array(VI.length).fill(0); + this.vertexData = Array(TxSprite.dataSize).fill(0); this.updateMap = { x: 0, y: 0, s: 0, r: 0, g: 0, b: 0, a: 0 @@ -32,6 +34,7 @@ export default class TxSprite { this.minX = minX; this.maxX = maxX; + this.minY = minY; this.maxY = maxY; this.attributes = { @@ -86,18 +89,24 @@ export default class TxSprite { minDuration: minimum remaining transition duration when adjust = true temp: if true, this update is only temporary (can be reversed with 'resume') */ - update(params: SpriteUpdateParams, minX?: number, maxX?: number, maxY?: number): void { + update(params: SpriteUpdateParams, minX?: number, maxX?: number, minY?: number, maxY?: number): void { const offsetTime = params.start || performance.now(); const v = params.duration > 0 ? (1 / params.duration) : 0; if (minX != null) { this.minX = minX; } + if (maxX != null) { + this.maxX = maxX; + } + if (minY != null) { + this.minY = minY; + } if (maxY != null) { this.maxY = maxY; } - updateKeys.forEach(key => { + attributeKeys.forEach(key => { this.updateMap[key] = params[key]; }); @@ -155,23 +164,32 @@ export default class TxSprite { ...this.tempAttributes }; } - const size = attributes.s; - const s = size.b; - const y = attributes.y.b; - const maxYFactor = (this.maxY - y) / s; - const x = attributes.x.b; - const maxXFactor = -(x - this.minX) / s; // update vertex data in place // ugly, but avoids overhead of allocating large temporary arrays - const vertexStride = VI.length + 2; + const vertexStride = VI.length + 4; for (let vertex = 0; vertex < 6; vertex++) { - this.vertexData[vertex * vertexStride] = Math.max(maxXFactor, vertexOffsetFactors[vertex][0]); - this.vertexData[(vertex * vertexStride) + 1] = Math.min(maxYFactor, vertexOffsetFactors[vertex][1]); - for (let step = 0; step < VI.length; step++) { + this.vertexData[vertex * vertexStride] = this.minX; + this.vertexData[(vertex * vertexStride) + 1] = this.minY; + this.vertexData[(vertex * vertexStride) + 2] = this.maxX; + this.vertexData[(vertex * vertexStride) + 3] = this.maxY; + + // x + this.vertexData[(vertex * vertexStride) + 4] = attributes[VI[0].a][VI[0].f] + (vertexOffsetFactors[vertex][0] * attributes.s.a); + this.vertexData[(vertex * vertexStride) + 5] = attributes[VI[1].a][VI[1].f] + (vertexOffsetFactors[vertex][0] * attributes.s.b); + this.vertexData[(vertex * vertexStride) + 6] = attributes[VI[2].a][VI[2].f]; + this.vertexData[(vertex * vertexStride) + 7] = attributes[VI[3].a][VI[3].f]; + + // y + this.vertexData[(vertex * vertexStride) + 8] = attributes[VI[4].a][VI[4].f] + (vertexOffsetFactors[vertex][1] * attributes.s.a); + this.vertexData[(vertex * vertexStride) + 9] = attributes[VI[5].a][VI[5].f] + (vertexOffsetFactors[vertex][1] * attributes.s.b); + this.vertexData[(vertex * vertexStride) + 10] = attributes[VI[6].a][VI[6].f]; + this.vertexData[(vertex * vertexStride) + 11] = attributes[VI[7].a][VI[7].f]; + + for (let step = 8; step < VI.length; step++) { // components of each field in the vertex array are defined by an entry in VI: // VI[i].a is the attribute, VI[i].f is the inner field, VI[i].offA and VI[i].offB are offset factors - this.vertexData[(vertex * vertexStride) + step + 2] = attributes[VI[step].a][VI[step].f]; + this.vertexData[(vertex * vertexStride) + step + 4] = attributes[VI[step].a][VI[step].f]; } } @@ -217,12 +235,12 @@ function interpolateAttributeStart(attribute: InterpolatedAttribute, start: DOMH } const vertexOffsetFactors = [ - [-1, 0], - [0, 1], [0, 0], - [-1, 0], - [0, 1], - [-1, 1] + [1, 1], + [1, 0], + [0, 0], + [1, 1], + [0, 1] ]; const VI = []; diff --git a/frontend/src/app/components/block-overview-graph/tx-view.ts b/frontend/src/app/components/block-overview-graph/tx-view.ts index 8607cca93..233ef36ea 100644 --- a/frontend/src/app/components/block-overview-graph/tx-view.ts +++ b/frontend/src/app/components/block-overview-graph/tx-view.ts @@ -106,7 +106,7 @@ export default class TxView implements TransactionStripped { returns minimum transition end time */ - update(params: ViewUpdateParams, { minX, maxX, maxY }: { minX: number, maxX: number, maxY: number }): number { + update(params: ViewUpdateParams, { minX, maxX, minY, maxY }: { minX: number, maxX: number, minY: number, maxY: number }): number { if (params.jitter) { params.delay += (Math.random() * params.jitter); } @@ -118,6 +118,7 @@ export default class TxView implements TransactionStripped { this.vertexArray, minX, maxX, + minY, maxY ); // apply any pending hover event @@ -132,6 +133,7 @@ export default class TxView implements TransactionStripped { }, minX, maxX, + minY, maxY ); } @@ -140,6 +142,7 @@ export default class TxView implements TransactionStripped { toSpriteUpdate(params), minX, maxX, + minY, maxY ); } diff --git a/frontend/src/app/components/block-overview-multi/block-overview-multi.component.ts b/frontend/src/app/components/block-overview-multi/block-overview-multi.component.ts index 0b2c6d883..6c6c3eee4 100644 --- a/frontend/src/app/components/block-overview-multi/block-overview-multi.component.ts +++ b/frontend/src/app/components/block-overview-multi/block-overview-multi.component.ts @@ -568,10 +568,9 @@ export class BlockOverviewMultiComponent implements AfterViewInit, OnDestroy, On // WebGL shader attributes const attribs = { - offset: { type: 'FLOAT', count: 2, pointer: null, offset: 0 }, + bounds: { type: 'FLOAT', count: 4, pointer: null, offset: 0 }, posX: { type: 'FLOAT', count: 4, pointer: null, offset: 0 }, posY: { type: 'FLOAT', count: 4, pointer: null, offset: 0 }, - posR: { type: 'FLOAT', count: 4, pointer: null, offset: 0 }, colR: { type: 'FLOAT', count: 4, pointer: null, offset: 0 }, colG: { type: 'FLOAT', count: 4, pointer: null, offset: 0 }, colB: { type: 'FLOAT', count: 4, pointer: null, offset: 0 }, @@ -594,10 +593,9 @@ varying lowp vec4 vColor; // each attribute contains [x: startValue, y: endValue, z: startTime, w: rate] // shader interpolates between start and end values at the given rate, from the given time -attribute vec2 offset; +attribute vec4 bounds; attribute vec4 posX; attribute vec4 posY; -attribute vec4 posR; attribute vec4 colR; attribute vec4 colG; attribute vec4 colB; @@ -622,10 +620,7 @@ float interpolateAttribute(vec4 attr) { void main() { vec4 screenTransform = vec4(2.0 / screenSize.x, 2.0 / screenSize.y, -1.0, -1.0); // vec4 screenTransform = vec4(1.0 / screenSize.x, 1.0 / screenSize.y, -0.5, -0.5); - - float radius = interpolateAttribute(posR); - vec2 position = vec2(interpolateAttribute(posX), interpolateAttribute(posY)) + (radius * offset); - + vec2 position = clamp(vec2(interpolateAttribute(posX), interpolateAttribute(posY)), bounds.xy, bounds.zw); gl_Position = vec4(position * screenTransform.xy + screenTransform.zw, 1.0, 1.0); float red = interpolateAttribute(colR); diff --git a/frontend/src/app/components/eight-mempool/eight-mempool.component.ts b/frontend/src/app/components/eight-mempool/eight-mempool.component.ts index b311d4372..8cc7d02cb 100644 --- a/frontend/src/app/components/eight-mempool/eight-mempool.component.ts +++ b/frontend/src/app/components/eight-mempool/eight-mempool.component.ts @@ -155,7 +155,7 @@ export class EightMempoolComponent implements OnInit, OnDestroy { this.lastBlockHeightUpdate = this.blockIndices.map(() => 0); this.autofit = params.autofit !== 'false'; this.blockWidth = Number.isInteger(Number(params.blockWidth)) ? Number(params.blockWidth) : 540; - this.padding = Number.isInteger(Number(params.padding)) ? Number(params.padding) : this.blockWidth; + this.padding = Number.isInteger(Number(params.padding)) ? Number(params.padding) : 0; this.wrapBlocks = params.wrap !== 'false'; this.stagger = Number.isInteger(Number(params.stagger)) ? Number(params.stagger) : 0; this.animationDuration = Number.isInteger(Number(params.animationDuration)) ? Number(params.animationDuration) : 2000;