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 = [];
|
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.
|
* Whether this chunk is located at the specified chunk reference.
|
||||||
* @param {ChunkReference} otherChunkRef The chunk reference to check
|
* @param {ChunkReference} otherChunkRef The chunk reference to check
|
||||||
|
@ -33,12 +47,34 @@ class Chunk
|
||||||
return false;
|
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)
|
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);
|
var planeSpaceRef = this.chunkRef.inPlaneSpace(this.size);
|
||||||
|
|
||||||
|
@ -47,16 +83,32 @@ class Chunk
|
||||||
|
|
||||||
for(let line of this.lines)
|
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.beginPath();
|
||||||
context.moveTo(
|
context.moveTo(
|
||||||
line.Points[0].x - planeSpaceRef.x,
|
linePoints[0].x - planeSpaceRef.x,
|
||||||
line.Points[0].y - planeSpaceRef.y
|
linePoints[0].y - planeSpaceRef.y
|
||||||
);
|
);
|
||||||
for(let i = 1; i < line.Points.length; i++)
|
|
||||||
|
for(let i = 1; i < linePoints.length; i++)
|
||||||
{
|
{
|
||||||
context.lineTo(
|
context.lineTo(
|
||||||
line.Points[i].x - planeSpaceRef.x,
|
linePoints[i].x - planeSpaceRef.x,
|
||||||
line.Points[i].y - planeSpaceRef.y
|
linePoints[i].y - planeSpaceRef.y
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,48 @@ class ChunkCache
|
||||||
this.boardWindow.rippleLink.on("ChunkUpdate", this.handleChunkUpdate.bind(this));
|
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.
|
* Adds the given chunk to the chunk cache.
|
||||||
* @param {Chunk} chunkData The chunk to add to the cache.
|
* @param {Chunk} chunkData The chunk to add to the cache.
|
||||||
|
@ -98,7 +140,7 @@ class ChunkCache
|
||||||
|
|
||||||
let chunk = this.cache.get(cChunk.toString());
|
let chunk = this.cache.get(cChunk.toString());
|
||||||
if(typeof chunk != "undefined" && !chunk.requestedFromServer)
|
if(typeof chunk != "undefined" && !chunk.requestedFromServer)
|
||||||
chunk.render(canvas, context);
|
chunk.render(canvas, context, this, chunkArea);
|
||||||
|
|
||||||
if(this.showRenderedChunks) {
|
if(this.showRenderedChunks) {
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
|
@ -125,6 +167,18 @@ class ChunkCache
|
||||||
let newChunk = new Chunk(newChunkRef, chunkData.Size);
|
let newChunk = new Chunk(newChunkRef, chunkData.Size);
|
||||||
let newLines = chunkData.lines.map((line) => {
|
let newLines = chunkData.lines.map((line) => {
|
||||||
line.Points = line.Points.map((raw) => new Vector(raw.X, raw.Y));
|
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;
|
return line;
|
||||||
});
|
});
|
||||||
newChunk.lines = newChunk.lines.concat(newLines);
|
newChunk.lines = newChunk.lines.concat(newLines);
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
import Vector from './Vector';
|
import Vector from './Vector';
|
||||||
|
|
||||||
/// <summary>
|
/**
|
||||||
/// Represents a rectangle in 2D space.
|
* Represents a rectangle in 2D space.
|
||||||
/// </summary>
|
*/
|
||||||
class Rectangle
|
class Rectangle
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -78,6 +78,22 @@ class Rectangle
|
||||||
this.height = height;
|
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 a copy of this rectangle that can be safely edited without affecting the original.
|
||||||
* @returns {Rectangle}
|
* @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>
|
/// <summary>
|
||||||
/// Gets a reference in chunk-space ot the chunk that this line starts in.
|
/// Gets a reference in chunk-space ot the chunk that this line starts in.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -120,6 +134,19 @@ namespace Nibriboard.RippleSpace
|
||||||
results.Add(nextLine);
|
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;
|
return results;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue