mirror of
https://github.com/sbrl/Nibriboard.git
synced 2018-01-10 21:33:49 +00:00
[server+client] Start working on the line-spanning-multiple-chunks issue, now that the last crisis has been averted :P
This commit is contained in:
parent
c4609ffd3a
commit
c3952f0778
4 changed files with 159 additions and 10 deletions
|
@ -19,6 +19,20 @@ class Chunk
|
|||
this.lines = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the first line in this chunk by it's id.
|
||||
* @param {string} lineId The target line id to search for.
|
||||
* @return {object|null} The requested line, or null if it wasn't found.
|
||||
*/
|
||||
getLineById(lineId)
|
||||
{
|
||||
for (let line of this.lines) {
|
||||
if(line.LineId == lineId)
|
||||
return line;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this chunk is located at the specified chunk reference.
|
||||
* @param {ChunkReference} otherChunkRef The chunk reference to check
|
||||
|
@ -33,12 +47,34 @@ class Chunk
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this chunk falls inside the specified rectangle.
|
||||
* @param {Rectangle} area The rectangle to test against, in location-space
|
||||
* @return {Boolean} Whether this chunk falls inside the specified rectangle.
|
||||
*/
|
||||
isVisible(area)
|
||||
{
|
||||
let chunkArea = new Rectangle(
|
||||
this.chunkRef.x * this.size,
|
||||
this.chunkRef.y * this.size,
|
||||
this.size, this.size
|
||||
);
|
||||
return area.overlaps(area);
|
||||
}
|
||||
|
||||
update(dt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
render(canvas, context)
|
||||
/**
|
||||
* Renders this chunk to the given canvas with the given context.
|
||||
* @param {HTMLCanvasElement} canvas The canvas to render to.
|
||||
* @param {CanvasRenderingContext2D} context The context to render with.
|
||||
* @param {ChunkCache} chunkCache The chunk cache to use to fetch data from surrounding chunks.
|
||||
* @param {Rectangle} chunkArea The area in which chunks are being rendered.
|
||||
*/
|
||||
render(canvas, context, chunkCache, chunkArea)
|
||||
{
|
||||
var planeSpaceRef = this.chunkRef.inPlaneSpace(this.size);
|
||||
|
||||
|
@ -47,16 +83,32 @@ class Chunk
|
|||
|
||||
for(let line of this.lines)
|
||||
{
|
||||
// Don't draw lines that are walked by other chunks
|
||||
if(line.ContinuesFrom != null &&
|
||||
chunkCache.fetchChunk(line.ContinuesFrom) != null)
|
||||
continue;
|
||||
|
||||
let linePoints = line.Points;
|
||||
|
||||
// Fetch all the points on fragments of this line forwards from here
|
||||
if(line.ContinuesIn != null) {
|
||||
let nextLines = chunkCache.fetchLineFragments(line.ContinuesIn, line.LineId);
|
||||
for (let nextLine of nextLines) {
|
||||
linePoints = linePoints.concat(nextLine.Points);
|
||||
}
|
||||
}
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(
|
||||
line.Points[0].x - planeSpaceRef.x,
|
||||
line.Points[0].y - planeSpaceRef.y
|
||||
linePoints[0].x - planeSpaceRef.x,
|
||||
linePoints[0].y - planeSpaceRef.y
|
||||
);
|
||||
for(let i = 1; i < line.Points.length; i++)
|
||||
|
||||
for(let i = 1; i < linePoints.length; i++)
|
||||
{
|
||||
context.lineTo(
|
||||
line.Points[i].x - planeSpaceRef.x,
|
||||
line.Points[i].y - planeSpaceRef.y
|
||||
linePoints[i].x - planeSpaceRef.x,
|
||||
linePoints[i].y - planeSpaceRef.y
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,48 @@ class ChunkCache
|
|||
this.boardWindow.rippleLink.on("ChunkUpdate", this.handleChunkUpdate.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the chunk with the specified chunk reference.
|
||||
* @param {ChunkReference} chunkRef The chunk reference of the chunk to fetch.
|
||||
* @return {Chunk|null} The requested chunk, or null if it isn't present in the cache.
|
||||
*/
|
||||
fetchChunk(chunkRef)
|
||||
{
|
||||
if(!this.cache.has(chunkRef.toString()))
|
||||
return null;
|
||||
|
||||
return this.cache.get(chunkRef.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk the currently cached chunks to find all the line fragments for the
|
||||
* specified line id, starting at the specified chunk reference.
|
||||
* @param {ChunkReference} startingChunkRef The reference of hte chunk we should start walking at.
|
||||
* @param {string} lineId The id of the line we should fetch the fragments for.
|
||||
* @return {object[]} A list of line fragments found.
|
||||
*/
|
||||
fetchLineFragments(startingChunkRef, lineId)
|
||||
{
|
||||
let lineFragments = [];
|
||||
let currentChunk = this.fetchChunk(startingChunkRef);
|
||||
|
||||
while(currentChunk != null)
|
||||
{
|
||||
let nextLineFragment = currentChunk.getLineById(lineId);
|
||||
if(nextLineFragment == null)
|
||||
break;
|
||||
|
||||
lineFragments.push(nextLineFragment);
|
||||
|
||||
if(nextLineFragment.ContinuesIn == null)
|
||||
break;
|
||||
|
||||
currentChunk = this.fetchChunk(nextLineFragment.ContinuesIn);
|
||||
}
|
||||
|
||||
return lineFragments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given chunk to the chunk cache.
|
||||
* @param {Chunk} chunkData The chunk to add to the cache.
|
||||
|
@ -98,7 +140,7 @@ class ChunkCache
|
|||
|
||||
let chunk = this.cache.get(cChunk.toString());
|
||||
if(typeof chunk != "undefined" && !chunk.requestedFromServer)
|
||||
chunk.render(canvas, context);
|
||||
chunk.render(canvas, context, this, chunkArea);
|
||||
|
||||
if(this.showRenderedChunks) {
|
||||
context.beginPath();
|
||||
|
@ -125,6 +167,18 @@ class ChunkCache
|
|||
let newChunk = new Chunk(newChunkRef, chunkData.Size);
|
||||
let newLines = chunkData.lines.map((line) => {
|
||||
line.Points = line.Points.map((raw) => new Vector(raw.X, raw.Y));
|
||||
if(line.ContinuesIn != null) {
|
||||
line.ContinuesIn = new ChunkReference(
|
||||
this.boardWindow.currentPlaneName,
|
||||
line.ContinuesIn.X, line.ContinuesIn.Y
|
||||
);
|
||||
}
|
||||
if(line.ContinuesFrom != null) {
|
||||
line.ContinuesFrom = new ChunkReference(
|
||||
this.boardWindow.currentPlaneName,
|
||||
line.ContinuesFrom.X, line.ContinuesFrom.Y
|
||||
);
|
||||
}
|
||||
return line;
|
||||
});
|
||||
newChunk.lines = newChunk.lines.concat(newLines);
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
import Vector from './Vector';
|
||||
|
||||
/// <summary>
|
||||
/// Represents a rectangle in 2D space.
|
||||
/// </summary>
|
||||
/**
|
||||
* Represents a rectangle in 2D space.
|
||||
*/
|
||||
class Rectangle
|
||||
{
|
||||
/**
|
||||
|
@ -78,6 +78,22 @@ class Rectangle
|
|||
this.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Figures out whether this rectangle overlaps another rectangle.
|
||||
* @param {Rectangle} otherRectangle The other rectangle to check the overlap of.
|
||||
* @return {bool} Whether this rectangle overlaps another rectangle.
|
||||
*/
|
||||
overlaps(otherRectangle)
|
||||
{
|
||||
if(this.Top > otherRectangle.Bottom ||
|
||||
this.Bottom < otherRectangle.Top ||
|
||||
this.Left > otherRectangle.Right ||
|
||||
this.Right < otherRectangle.Left)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this rectangle that can be safely edited without affecting the original.
|
||||
* @returns {Rectangle}
|
||||
|
|
|
@ -59,6 +59,20 @@ namespace Nibriboard.RippleSpace
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The chunk reference of the next chunk that this line continues in.
|
||||
/// A value of null is present when this line doesn't continue into another chunk.
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
public ChunkReference ContinuesIn = null;
|
||||
/// <summary>
|
||||
/// The chunk reference of the previous chunk that contains the line fragment that
|
||||
/// this line continues from. Is null when this line either doesn't continue from
|
||||
/// another line fragment or doesn't span multiple chunks.
|
||||
/// </summary>
|
||||
[JsonProperty]
|
||||
public ChunkReference ContinuesFrom = null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a reference in chunk-space ot the chunk that this line starts in.
|
||||
/// </summary>
|
||||
|
@ -120,6 +134,19 @@ namespace Nibriboard.RippleSpace
|
|||
results.Add(nextLine);
|
||||
}
|
||||
|
||||
// Set the ContinuesIn and ContinuesFrom properties
|
||||
// so that clients can find the next / previous chunk line fragmentss
|
||||
for(int i = 0; i < results.Count - 1; i++)
|
||||
{
|
||||
// Set the ContinuesFrom reference, but not on the first fragment in the list
|
||||
if(i > 0)
|
||||
results[i].ContinuesFrom = results[i - 1].ContainingChunk;
|
||||
|
||||
// Set the ContinuesIn reference, but not on the last fragment in the list
|
||||
if(i < results.Count - 1)
|
||||
results[i].ContinuesIn = results[i + 1].ContainingChunk;
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue