Ignore:
Timestamp:
12/12/24 17:06:06 (5 weeks ago)
Author:
stefan toskovski <stefantoska84@…>
Branches:
main
Parents:
d565449
Message:

Pred finalna verzija

Location:
imaps-frontend/src/scripts
Files:
12 added
1 deleted
14 edited
1 moved

Legend:

Unmodified
Added
Removed
  • imaps-frontend/src/scripts/base/MapShape.js

    rd565449 r0c6b92a  
    66            throw new Error("Cannot instantiate abstract class BaseShape directly.");
    77        }
     8
     9        console.log(config.x,"FFF");
    810        super(config);
    911        this.layer = layer;
     
    1214        this.snappable = snap;
    1315        this._info = {};
    14         this.modalEventName = "";
     16        this.eventName = "";
    1517        this.infoText = null;
     18        this.floorNum;
    1619
    1720        this.shadowForStrokeEnabled(false);
    1821        this.on("mouseover", () => (document.body.style.cursor = "pointer"));
    1922        this.on("mouseout", () => (document.body.style.cursor = "default"));
    20         // this.on("dblclick", (e) => {
    21         //   this.moveToTop();
    22         //   this.getLayer()
    23         //     .find("Transformer")
    24         //     .forEach((t) => t.moveToTop());
    25         // });
     23        this.on("click", (e) => {
     24            if(e.evt.altKey){
     25                this.moveToTop();
     26                this.getLayer()
     27                    .find("Transformer")
     28                    .forEach((t) => t.moveToTop());
     29            }
     30
     31        });
    2632
    2733        if (snap) {
    2834            this.on("dragend", this.snapToGrid.bind(this));
    29             this.on('dblclick', this.snapToGrid.bind(this))
     35            this.on('dblclick', this.snapToGrid.bind(this));
    3036        }
    3137
     
    3642        });
    3743
    38         this.on('dragend', () => {
     44
     45        this.on('dragmove', () => {
    3946            if (this.infoText) {
    4047                this.updateTextPosition();
     
    7683    }
    7784
     85
     86    destroy() {
     87        super.destroy();
     88        if (this.infoText !== null) {
     89            this.infoText.remove()
     90            console.log("cleared text")
     91        }
     92    }
     93
     94    setInfo(infoObj){
     95        this.info = infoObj;
     96    }
     97
     98    load(){
     99        console.log("Abstract function")
     100    }
     101
    78102    _sceneFunc(context) {
    79103        let width = this.width();
     
    93117    }
    94118
     119    updateText(shapeName){
     120            this.infoText.text = shapeName;
     121            console.log("Updated text to : " + shapeName)
     122    }
     123
    95124    snapToGrid() {
    96125        this.position({
     
    98127            y: Math.round(this.y() / this.blockSize) * this.blockSize,
    99128        });
     129
    100130    }
    101131
  • imaps-frontend/src/scripts/main/MapBuilder.js

    rd565449 r0c6b92a  
    22import Konva from "konva";
    33import HttpService from "../net/HttpService.js";
    4 import { zoomStage } from "../util/zoomStage.js";
     4import {zoomStage} from "../util/zoomStage.js";
     5import {addEventHandling} from "../util/addEventHandling.js";
     6import MapNode from "../base/MapNode.js";
     7import {json} from "react-router-dom";
     8import log from "eslint-plugin-react/lib/util/log.js";
     9import ShapeRegistry from "../util/ShapeRegistry.js";
     10import shapeRegistry from "../util/ShapeRegistry.js";
     11import triggerMapSave from "../util/triggerMapSave.js";
    512
    613export class MapBuilder {
    7   constructor(containerId) {
    8     this.container = document.getElementById(containerId);
    9     this.stage = new Konva.Stage({
    10       container: containerId,
    11       width: this.container.clientWidth,
    12       height: this.container.clientHeight,
    13     });
    14 
    15     // TODO AKO DRAGNIT NEKOJ OD POCETOK NA STAGE POZICIIVE KE SA ZEZNAT
    16     // TODO jwt vo cookie
    17     // TODO placed shape i mouseMoveHandler da ne callback ( da ne vrakjat funkcija)
    18 
    19     this.gridLayer = new Konva.Layer();
    20     this.mainLayer = new Konva.Layer();
    21     this.dragLayer = new Konva.Layer();
    22     this.infoPinLayer = new Konva.Layer();
    23     this.textLayer = new Konva.Layer();
    24     this.gridLayer.listening(false);
    25 
    26     this.originalWidth = this.container.clientWidth;
    27     this.originalHeight = this.container.clientHeight;
    28 
    29     this.shapes = [];
    30     this.blockSize = 10;
    31     this.efficientDrawingMode = false;
    32     this.roomTypes = [];
    33 
    34     this.gridLine = new Konva.Line({
    35       points: [],
    36       stroke: "grey",
    37       strokeWidth: 1,
    38       opacity: 0.3,
    39     });
    40 
    41     this.gridLine.cache();
    42 
    43     this.mainTransformer = new Konva.Transformer({
    44       centeredScaling: false,
    45       rotationSnaps: [0, 90, 180, 270],
    46       anchorSize: 5,
    47       padding: 2,
    48       anchorFill: "#ef7539",
    49       borderStroke: "black",
    50       anchorStroke: "black",
    51       cornerRadius: 20,
    52       anchorCornerRadius: 10,
    53       anchorDragBoundFunc: this.transformerSnapFunc(),
    54     });
    55 
    56     this.selectionRectangle = new Konva.Rect({
    57       fill: "rgba(200,0,255,0.5)",
    58       visible: false,
    59       listening: false,
    60       zIndex: 100,
    61     });
    62 
    63     this.x1 = 0;
    64     this.y1 = 0;
    65     this.x2 = 0;
    66     this.y2 = 0;
    67 
    68     this.selecting = false;
    69 
    70     this.initialize();
    71   }
    72 
    73   initialize() {
    74     this.drawGrid();
    75     this.mainLayer.add(this.mainTransformer);
    76     this.mainLayer.add(this.selectionRectangle);
    77     this.stage.add(this.gridLayer);
    78     this.stage.add(this.dragLayer);
    79     this.stage.add(this.mainLayer);
    80     this.stage.add(this.infoPinLayer);
    81     this.stage.add(this.textLayer);
    82     this.setupEventListeners();
    83   }
    84 
    85   setupEventListeners() {
    86     document.getElementById("shapeOptions").addEventListener("click", this.selectShape.bind(this));
    87     document.getElementById("render-button").addEventListener("click", this.render.bind(this));
    88     window.addEventListener("keydown", this.handleExitSelection.bind(this));
    89     window.addEventListener("keydown", this.handleDelete.bind(this));
    90     window.addEventListener("keydown", this.rotateShapesBy90Deg.bind(this));
    91     window.addEventListener("keydown", this.toggleEfficientDrawingMode.bind(this));
    92     window.addEventListener("resize", this.handleResize.bind(this));
    93     this.stage.on("mousedown touchstart", this.handleMouseDown.bind(this));
    94     this.stage.on("mousemove touchmove", this.handleMouseMove.bind(this));
    95     this.stage.on("mouseup touchend", this.handleMouseUp.bind(this));
    96     this.stage.on("click tap", this.handleStageClick.bind(this));
    97     this.stage.on("contextmenu", this.placeInfoPin.bind(this));
    98     this.stage.on("dragmove", this.dragStage.bind(this));
    99     this.stage.on("wheel", this.zoom.bind(this));
    100   }
    101 
    102   detachKeyPressEventListeners() {
    103     window.removeEventListener("keydown", this.handleExitSelection.bind(this));
    104     window.removeEventListener("keydown", this.handleDelete.bind(this));
    105     window.removeEventListener("keydown", this.rotateShapesBy90Deg.bind(this));
    106     window.removeEventListener("keydown", this.toggleEfficientDrawingMode.bind(this));
    107   }
    108   attachKeyPressEventListeners() {
    109     window.addEventListener("keydown", this.handleExitSelection.bind(this));
    110     window.addEventListener("keydown", this.handleDelete.bind(this));
    111     window.addEventListener("keydown", this.rotateShapesBy90Deg.bind(this));
    112     window.addEventListener("keydown", this.toggleEfficientDrawingMode.bind(this));
    113   }
    114 
    115   dragStage(e) {
    116     if (!e.evt.shiftKey) return;
    117     this.drawGrid();
    118   }
    119 
    120   transformerSnapFunc() {
    121     return (oldPos, newPos) => {
    122       const snapDistance = 8;
    123 
    124       if (this.mainTransformer.getActiveAnchor() === "rotater") {
    125         return newPos;
    126       }
    127 
    128       const distance = Math.sqrt(Math.pow(newPos.x - oldPos.x, 2) + Math.pow(newPos.y - oldPos.y, 2));
    129 
    130       if (distance > snapDistance) {
    131         return newPos;
    132       }
    133 
    134       const nextX = Math.round(newPos.x / this.blockSize) * this.blockSize;
    135       const diffX = Math.abs(newPos.x - nextX);
    136 
    137       const nextY = Math.round(newPos.y / this.blockSize) * this.blockSize;
    138       const diffY = Math.abs(newPos.y - nextY);
    139 
    140       const snapToX = diffX < snapDistance;
    141       const snapToY = diffY < snapDistance;
    142 
    143       if (snapToX && !snapToY) {
     14    constructor(containerId,floorNum,mapName) {
     15        this.container = document.getElementById(containerId);
     16        this.stage = new Konva.Stage({
     17            container: containerId,
     18            width: this.container.clientWidth,
     19            height: this.container.clientHeight,
     20        });
     21
     22        // TODO AKO DRAGNIT NEKOJ OD POCETOK NA STAGE POZICIIVE KE SA ZEZNAT
     23        // TODO jwt vo cookie
     24        // TODO placed shape i mouseMoveHandler da ne callback ( da ne vrakjat funkcija)
     25        // TODO text na top layer sekogas
     26
     27        this._floorNum = floorNum;
     28        this.mapName = mapName;
     29
     30        this.gridLayer = new Konva.Layer();
     31        this.mainLayer = new Konva.Layer();
     32        this.dragLayer = new Konva.Layer();
     33        this.infoPinLayer = new Konva.Layer();
     34        this.prioLayer = new Konva.Layer();
     35        this.textLayer = new Konva.Layer();
     36        this.gridLayer.listening(false);
     37
     38
     39        this.othStairs = [];
     40
     41        this.blockSize = 10;
     42        this.efficientDrawingMode = false;
     43        this.roomTypes = [];
     44
     45        this.gridLine = new Konva.Line({
     46            points: [],
     47            stroke: "grey",
     48            strokeWidth: 1,
     49            opacity: 0.3,
     50        });
     51
     52        this.gridLine.cache();
     53
     54        this.mainTransformer = new Konva.Transformer({
     55            centeredScaling: false,
     56            rotationSnaps: [0, 90, 180, 270],
     57            anchorSize: 5,
     58            padding: 2,
     59            anchorFill: "#f6031f",
     60            borderStroke: "black",
     61            anchorStroke: "black",
     62            cornerRadius: 20,
     63            anchorCornerRadius: 10,
     64            anchorDragBoundFunc: this.transformerSnapFunc(),
     65        });
     66
     67        this.selectionRectangle = new Konva.Rect({
     68            fill: "rgba(56,194,245,0.5)",
     69            visible: false,
     70            listening: false,
     71            zIndex: 100,
     72        });
     73
     74        this.x1 = 0;
     75        this.y1 = 0;
     76        this.x2 = 0;
     77        this.y2 = 0;
     78
     79        this.selecting = false;
     80
     81        this.initialize();
     82    }
     83
     84    initialize() {
     85        this.drawGrid();
     86        this.mainLayer.add(this.mainTransformer);
     87        this.mainLayer.add(this.selectionRectangle);
     88        this.stage.add(this.gridLayer);
     89        this.stage.add(this.dragLayer);
     90        this.stage.add(this.mainLayer);
     91        this.stage.add(this.infoPinLayer);
     92        this.stage.add(this.textLayer);
     93        this.setupEventListeners();
     94    }
     95
     96    setupEventListeners() {
     97        document.getElementById("shapeOptions").addEventListener("click", this.selectShape.bind(this));
     98        window.addEventListener("keydown", this.handleExitSelection.bind(this));
     99        window.addEventListener("keydown", this.handleDelete.bind(this));
     100        window.addEventListener("keydown", this.rotateShapesBy90Deg.bind(this));
     101        window.addEventListener("keydown", this.toggleEfficientDrawingMode.bind(this));
     102        window.addEventListener("resize", this.handleResize.bind(this));
     103
     104        this.boundEscapeEventListener = this.handleExitSelection.bind(this);
     105        this.boundDeleteEventListener = this.handleDelete.bind(this);
     106        this.boundRotateShapeEventListener = this.rotateShapesBy90Deg.bind(this)
     107        this.boundEfficientDrawingModeEventListener = this.toggleEfficientDrawingMode.bind(this);
     108
     109        //this.attachKeyPressEventListeners();
     110
     111        this.stage.on("mousedown touchstart", this.handleMouseDown.bind(this));
     112        this.stage.on("mousemove touchmove", this.handleMouseMove.bind(this));
     113        this.stage.on("mouseup touchend", this.handleMouseUp.bind(this));
     114        this.stage.on("click tap", this.handleStageClick.bind(this));
     115        this.stage.on("contextmenu", this.placeInfoPin.bind(this));
     116        this.stage.on("dragmove", this.dragStage.bind(this));
     117        this.stage.on("wheel", this.zoom.bind(this));
     118    }
     119
     120    detachKeyPressEventListeners() {
     121        window.removeEventListener("keydown", this.boundEscapeEventListener);
     122        window.removeEventListener("keydown", this.boundDeleteEventListener);
     123        window.removeEventListener("keydown", this.boundRotateShapeEventListener);
     124        window.removeEventListener("keydown", this.boundEfficientDrawingModeEventListener);
     125    }
     126
     127    attachKeyPressEventListeners() {
     128        window.addEventListener("keydown", this.boundEscapeEventListener);
     129        window.addEventListener("keydown", this.boundDeleteEventListener);
     130        window.addEventListener("keydown", this.boundRotateShapeEventListener);
     131        window.addEventListener("keydown", this.boundEfficientDrawingModeEventListener);
     132    }
     133
     134    dragStage(e) {
     135        if (!e.evt.shiftKey) return;
     136        this.drawGrid();
     137    }
     138
     139    transformerSnapFunc() {
     140        return (oldPos, newPos) => {
     141            const snapDistance = 8;
     142
     143            if (this.mainTransformer.getActiveAnchor() === "rotater") {
     144                return newPos;
     145            }
     146
     147            const distance = Math.sqrt(Math.pow(newPos.x - oldPos.x, 2) + Math.pow(newPos.y - oldPos.y, 2));
     148
     149            if (distance > snapDistance) {
     150                return newPos;
     151            }
     152
     153            const nextX = Math.round(newPos.x / this.blockSize) * this.blockSize;
     154            const diffX = Math.abs(newPos.x - nextX);
     155
     156            const nextY = Math.round(newPos.y / this.blockSize) * this.blockSize;
     157            const diffY = Math.abs(newPos.y - nextY);
     158
     159            const snapToX = diffX < snapDistance;
     160            const snapToY = diffY < snapDistance;
     161
     162            if (snapToX && !snapToY) {
     163                return {
     164                    x: nextX,
     165                    y: oldPos.y,
     166                };
     167            } else if (!snapToX && snapToY) {
     168                return {
     169                    x: oldPos.x,
     170                    y: nextY,
     171                };
     172            } else if (snapToX && snapToY) {
     173                return {
     174                    x: nextX,
     175                    y: nextY,
     176                };
     177            }
     178
     179            return newPos;
     180        };
     181    }
     182
     183    handleResize() {
     184        this.stage.width(this.container.offsetWidth);
     185        this.stage.height(this.container.offsetHeight);
     186        this.drawGrid();
     187    }
     188
     189    zoom(e) {
     190        zoomStage(e, this.stage, true);
     191        this.drawGrid();
     192    }
     193
     194    get floorNum(){
     195        return this._floorNum;
     196    }
     197
     198    set floorNum(val){
     199        this._floorNum = val;
     200    }
     201
     202    drawGrid() {
     203        this.gridLayer.destroyChildren();
     204
     205        let width = this.stage.width();
     206        let height = this.stage.height();
     207
     208        //presmetka od globalen koordinaten sistem vo lokalen na canvasot
     209        let transform = this.stage.getAbsoluteTransform().copy().invert();
     210        let topLeft = transform.point({
     211            x: 0,
     212            y: 0,
     213        });
     214
     215        let bottomRight = transform.point({
     216            x: width,
     217            y: height,
     218        });
     219
     220        let startX = Math.floor(topLeft.x / this.blockSize) * this.blockSize;
     221        let startY = Math.floor(topLeft.y / this.blockSize) * this.blockSize;
     222
     223        let endX = Math.ceil(bottomRight.x / this.blockSize) * this.blockSize;
     224        let endY = Math.ceil(bottomRight.y / this.blockSize) * this.blockSize;
     225
     226        for (let x = startX; x <= endX; x += this.blockSize) {
     227            let line = this.gridLine.clone({
     228                points: [x + 0.5, topLeft.y - this.blockSize, x + 0.5, bottomRight.y + this.blockSize],
     229            });
     230
     231            line.transformsEnabled("position");
     232            line.perfectDrawEnabled(false);
     233            line.shadowForStrokeEnabled(false);
     234
     235            this.gridLayer.add(line);
     236        }
     237
     238        for (let y = startY; y <= endY; y += this.blockSize) {
     239            let line = this.gridLine.clone({
     240                points: [topLeft.x - this.blockSize, y + 0.5, bottomRight.x + this.blockSize, y + 0.5],
     241            });
     242
     243            line.perfectDrawEnabled(false);
     244            line.shadowForStrokeEnabled(false);
     245            line.transformsEnabled("position");
     246            this.gridLayer.add(line);
     247        }
     248
     249        this.mainLayer.moveToTop();
     250        this.infoPinLayer.moveToTop();
     251
     252        this.gridLayer.batchDraw();
     253    }
     254
     255    placeInfoPin(e) {
     256        e.evt.preventDefault();
     257        let mousePos = this.stage.getRelativePointerPosition();
     258        const attrs = {
     259            type: "InfoPin",
     260            position: mousePos,
     261            blockSize: this.blockSize,
     262            layer: this.mainLayer,
     263            rotation: 0,
     264            scaleX: 1,
     265            scaleY: 1,
     266            increment: true,
     267            floorNum: this.floorNum
     268        };
     269        let infoPin = Factory.createShape("InfoPin", attrs);
     270        addEventHandling(infoPin, this, "dblclick");
     271        //this.shapes.push(infoPin);
     272        ShapeRegistry.add(infoPin)
     273        this.mainLayer.add(infoPin);
     274        infoPin.displayName(this.textLayer);
     275        triggerMapSave()
     276
     277        console.log(infoPin.name());
     278    }
     279
     280    toggleEfficientDrawingMode(e) {
     281        if (e.key === "e" || e.key === "E") {
     282            this.efficientDrawingMode = !this.efficientDrawingMode;
     283            console.log("EFFICIENT DRAWING MODE is: ", this.efficientDrawingMode);
     284
     285            if (!this.efficientDrawingMode) {
     286                this.stopDrawing();
     287            }
     288        }
     289    }
     290
     291    placeShape() {
     292        const mousePos = this.stage.getRelativePointerPosition();
     293        const attrs = {
     294            position: mousePos,
     295            width: this.blockSize,
     296            height: this.blockSize,
     297            layer: this.mainLayer,
     298            rotation: this.hoverObj.rotation(),
     299            scaleX: 1,
     300            scaleY: 1,
     301            increment: true,
     302            snap: true,
     303            fromLoad: false,
     304            blockSize: this.blockSize,
     305            floorNum: this.floorNum
     306        };
     307
     308        const placedObj = Factory.createShape(this.hoverObj.type, attrs);
     309        if (!placedObj) return;
     310
     311        console.info("ATTRS FNUM",attrs.floorNum)
     312
     313        this.mainLayer.add(placedObj);
     314        //this.shapes.push(placedObj);
     315        console.log("VO PLACED SHAEPS WALL ZITI SE: " + placedObj.className);
     316        ShapeRegistry.add(placedObj);
     317        addEventHandling(placedObj, this, "dblclick");
     318        this.mainLayer.draw();
     319
     320        // site ovie func da se vo edna funkcija vo shape.
     321
     322        placedObj.displayName(this.textLayer);
     323        placedObj.snapToGrid();
     324
     325        triggerMapSave();
     326
     327        if (!this.efficientDrawingMode) {
     328            this.stopDrawing();
     329        }
     330    }
     331
     332    stopDrawing() {
     333        this.mainTransformer.nodes([]);
     334        if (this.hoverObj != null) this.hoverObj.remove();
     335        this.dragLayer.removeChildren();
     336        this.stage.off("mousemove", this.boundMouseMoveHandler);
     337        this.stage.off("click", this.boundPlaceShapeHandler);
     338    }
     339
     340    mouseMoveHandler() {
     341        const mousePos = this.stage.getRelativePointerPosition();
     342        this.hoverObj.position({x: mousePos.x, y: mousePos.y});
     343        this.hoverObj.visible(true);
     344    }
     345
     346    startDrawing(shapeType) {
     347        const attrs = {
     348            position: {x: 0, y: 0},
     349            width: this.blockSize,
     350            height: this.blockSize,
     351            layer: this.mainLayer,
     352            rotation: 0,
     353            scaleX: 1,
     354            scaleY: 1,
     355            increment: false,
     356            snap: true,
     357            fromLoad: false,
     358            blockSize: this.blockSize
     359        };
     360        this.hoverObj = Factory.createShape(shapeType, attrs);
     361
     362        console.log("HOVBER OBK:", this.hoverObj)
     363
     364        this.hoverObj.visible(false);
     365        this.dragLayer.add(this.hoverObj);
     366        this.dragLayer.moveToTop();
     367        this.boundMouseMoveHandler = this.mouseMoveHandler.bind(this);
     368        this.boundPlaceShapeHandler = this.placeShape.bind(this);
     369
     370        this.stage.on("mousemove", this.boundMouseMoveHandler);
     371        this.stage.on("click", this.boundPlaceShapeHandler);
     372    }
     373
     374    selectShape(e) {
     375        if (e.target.tagName === "LI") {
     376            const shapeType = e.target.getAttribute("data-info");
     377            this.startDrawing(shapeType);
     378            this.mainTransformer.nodes([]);
     379        }
     380    }
     381
     382    rotateShapesBy90Deg(e) {
     383        if (e.key === "r" || e.key === "R") {
     384            if (this.hoverObj) {
     385                this.hoverObj.rotate(90);
     386            }
     387            this.mainTransformer.nodes().forEach((node) => {
     388                node.rotate(90);
     389            });
     390        }
     391    }
     392
     393    handleDelete(e) {
     394        if (e.key === "Delete") {
     395            this.mainTransformer.nodes().forEach((node) => {
     396                node.remove();
     397                node.destroy();
     398                ShapeRegistry.delete(node);
     399                triggerMapSave();
     400            });
     401            this.mainTransformer.nodes([]);
     402            this.mainLayer.batchDraw();
     403        }
     404    }
     405
     406    handleExitSelection(e) {
     407        if (e.key === "Escape") {
     408            this.mainTransformer.nodes([]);
     409            this.stopDrawing();
     410        }
     411    }
     412
     413    handleMouseDown(e) {
     414        this.stage.draggable(e.evt.shiftKey);
     415
     416        if (e.target !== this.stage) {
     417            return;
     418        }
     419
     420        e.evt.preventDefault();
     421        this.x1 = this.stage.getRelativePointerPosition().x;
     422        this.y1 = this.stage.getRelativePointerPosition().y;
     423        this.x2 = this.stage.getRelativePointerPosition().x;
     424        this.y2 = this.stage.getRelativePointerPosition().y;
     425
     426        this.selectionRectangle.width(0);
     427        this.selectionRectangle.height(0);
     428        this.selecting = true;
     429    }
     430
     431    handleMouseMove(e) {
     432        if (!this.selecting) {
     433            return;
     434        }
     435        e.evt.preventDefault();
     436        this.x2 = this.stage.getRelativePointerPosition().x;
     437        this.y2 = this.stage.getRelativePointerPosition().y;
     438
     439        this.selectionRectangle.setAttrs({
     440            visible: true,
     441            x: Math.min(this.x1, this.x2),
     442            y: Math.min(this.y1, this.y2),
     443            width: Math.abs(this.x2 - this.x1),
     444            height: Math.abs(this.y2 - this.y1),
     445        });
     446    }
     447
     448    handleMouseUp(e) {
     449        this.selecting = false;
     450        this.stage.draggable(false);
     451
     452        if (!this.selectionRectangle.visible()) {
     453            return;
     454        }
     455
     456        e.evt.preventDefault();
     457        this.selectionRectangle.visible(false);
     458        const shapes = this.stage.find(".mapObj");
     459        const box = this.selectionRectangle.getClientRect();
     460        const selected = shapes.filter((shape) => Konva.Util.haveIntersection(box, shape.getClientRect()));
     461        this.mainTransformer.nodes(selected);
     462        console.log(this.mainTransformer.nodes());
     463    }
     464
     465    saveShapeDetails() {
     466        // this.shapes.forEach(shape => {
     467        //     shape.saveShapeDetails();
     468        //     console.log(shape.info);
     469        // });
     470        ShapeRegistry.saveDetails();
     471        console.log("thisflornum",this.floorNum)
     472        return  {
     473            shapes: ShapeRegistry.getShapes(this.floorNum),
     474            roomTypes: JSON.stringify(this.roomTypes),
     475            mapName: this.mapName,
     476            floorNum: this.floorNum
     477        }
     478    }
     479
     480    getPayload(){
     481        this.saveShapeDetails();
    144482        return {
    145           x: nextX,
    146           y: oldPos.y,
    147         };
    148       } else if (!snapToX && snapToY) {
    149         return {
    150           x: oldPos.x,
    151           y: nextY,
    152         };
    153       } else if (snapToX && snapToY) {
    154         return {
    155           x: nextX,
    156           y: nextY,
    157         };
    158       }
    159 
    160       return newPos;
    161     };
    162   }
    163 
    164   handleResize() {
    165     this.stage.width(this.container.offsetWidth);
    166     this.stage.height(this.container.offsetHeight);
    167     this.drawGrid();
    168   }
    169 
    170   zoom(e) {
    171    zoomStage(e,this.stage);
    172    this.drawGrid();
    173   }
    174 
    175   drawGrid() {
    176     this.gridLayer.destroyChildren();
    177 
    178     let width = this.stage.width();
    179     let height = this.stage.height();
    180 
    181     //presmetka od globalen koordinaten sistem vo lokalen na canvasot
    182     let transform = this.stage.getAbsoluteTransform().copy().invert();
    183     let topLeft = transform.point({
    184       x: 0,
    185       y: 0,
    186     });
    187 
    188     let bottomRight = transform.point({
    189       x: width,
    190       y: height,
    191     });
    192 
    193     let startX = Math.floor(topLeft.x / this.blockSize) * this.blockSize;
    194     let startY = Math.floor(topLeft.y / this.blockSize) * this.blockSize;
    195 
    196     let endX = Math.ceil(bottomRight.x / this.blockSize) * this.blockSize;
    197     let endY = Math.ceil(bottomRight.y / this.blockSize) * this.blockSize;
    198 
    199     for (let x = startX; x <= endX; x += this.blockSize) {
    200       let line = this.gridLine.clone({
    201         points: [x + 0.5, topLeft.y - this.blockSize, x + 0.5, bottomRight.y + this.blockSize],
    202       });
    203 
    204       line.transformsEnabled("position");
    205       line.perfectDrawEnabled(false);
    206       line.shadowForStrokeEnabled(false);
    207 
    208       this.gridLayer.add(line);
    209     }
    210 
    211     for (let y = startY; y <= endY; y += this.blockSize) {
    212       let line = this.gridLine.clone({
    213         points: [topLeft.x - this.blockSize, y + 0.5, bottomRight.x + this.blockSize, y + 0.5],
    214       });
    215 
    216       line.perfectDrawEnabled(false);
    217       line.shadowForStrokeEnabled(false);
    218       line.transformsEnabled("position");
    219       this.gridLayer.add(line);
    220     }
    221 
    222     this.mainLayer.moveToTop();
    223     this.infoPinLayer.moveToTop();
    224 
    225     this.gridLayer.batchDraw();
    226   }
    227 
    228   placeInfoPin(e) {
    229     e.evt.preventDefault();
    230     let mousePos = this.stage.getRelativePointerPosition();
    231     let infoPin = Factory.createShape("InfoPin", mousePos, this.blockSize, this.mainLayer, 0,1,1,true);
    232     this.addModalHandling(infoPin);
    233     this.shapes.push(infoPin);
    234     this.mainLayer.add(infoPin)
    235     infoPin.displayName(this.textLayer);
    236     console.log(infoPin.name());
    237   }
    238 
    239   toggleEfficientDrawingMode(e) {
    240     if (e.key === "e" || e.key === "E") {
    241       this.efficientDrawingMode = !this.efficientDrawingMode;
    242       console.log("EFFICIENT DRAWING MODE is: ", this.efficientDrawingMode);
    243 
    244       if (!this.efficientDrawingMode) {
    245         this.stopDrawing();
    246       }
    247     }
    248   }
    249 
    250   placeShape() {
    251     const mousePos = this.stage.getRelativePointerPosition();
    252     const placedObj = Factory.createShape(
    253       this.hoverObj.type,
    254       mousePos,
    255       this.blockSize,
    256       this.mainLayer,
    257       this.hoverObj.rotation(),
    258         1,
    259         1,
    260         true
    261     );
    262 
    263     if (!placedObj) return;
    264 
    265     this.mainLayer.add(placedObj);
    266     this.shapes.push(placedObj);
    267     this.addModalHandling(placedObj);
    268     this.mainLayer.draw();
    269     placedObj.displayName(this.textLayer);
    270     placedObj.snapToGrid();
    271 
    272     if (!this.efficientDrawingMode) {
    273       this.stopDrawing();
    274     }
    275   }
    276 
    277   stopDrawing() {
    278     this.mainTransformer.nodes([]);
    279     this.hoverObj.remove();
    280     this.dragLayer.removeChildren();
    281     this.stage.off("mousemove", this.boundMouseMoveHandler);
    282     this.stage.off("click", this.boundPlaceShapeHandler);
    283   }
    284 
    285   mouseMoveHandler() {
    286     const mousePos = this.stage.getRelativePointerPosition();
    287     this.hoverObj.position({ x: mousePos.x, y: mousePos.y });
    288     this.hoverObj.visible(true);
    289   }
    290 
    291   startDrawing(shapeType) {
    292     let pos = { x: 0, y: 0 };
    293     this.hoverObj = Factory.createShape(shapeType, pos, this.blockSize, this.dragLayer, 0);
    294 
    295     this.hoverObj.visible(false);
    296     this.dragLayer.add(this.hoverObj);
    297     this.dragLayer.moveToTop();
    298     this.boundMouseMoveHandler = this.mouseMoveHandler.bind(this);
    299     this.boundPlaceShapeHandler = this.placeShape.bind(this);
    300 
    301     this.stage.on("mousemove", this.boundMouseMoveHandler);
    302     this.stage.on("click", this.boundPlaceShapeHandler);
    303   }
    304 
    305   selectShape(e) {
    306     if (e.target.tagName === "LI") {
    307       const shapeType = e.target.getAttribute("data-info");
    308       this.startDrawing(shapeType);
    309       this.mainTransformer.nodes([]);
    310     }
    311   }
    312 
    313   addModalHandling(shape) {
    314     shape.on("dblclick", () => {
    315       const eventName = shape.modalEventName;
    316       if (eventName) {
    317         const data = {
    318           room: shape,
    319           map: this,
    320         };
    321         const event = new CustomEvent(eventName, { detail: data });
    322         window.dispatchEvent(event);
    323       }
    324     });
    325   }
    326 
    327   rotateShapesBy90Deg(e) {
    328     if (e.key === "r" || e.key === "R") {
    329       if (this.hoverObj) {
    330         this.hoverObj.rotate(90);
    331       }
    332       this.mainTransformer.nodes().forEach((node) => {
    333         node.rotate(90);
    334       });
    335     }
    336   }
    337 
    338   handleDelete(e) {
    339     if (e.key === "Delete") {
    340       this.mainTransformer.nodes().forEach((node) => {
    341         node.remove();
    342         this.shapes.splice(this.shapes.indexOf(node), 1);
    343       });
    344       this.mainTransformer.nodes([]);
    345       this.mainLayer.batchDraw();
    346     }
    347   }
    348 
    349   handleExitSelection(e) {
    350     if (e.key === "Escape") {
    351       this.mainTransformer.nodes([]);
    352       this.stopDrawing();
    353     }
    354   }
    355 
    356   handleMouseDown(e) {
    357     this.stage.draggable(e.evt.shiftKey);
    358 
    359     if (e.target !== this.stage) {
    360       return;
    361     }
    362 
    363     e.evt.preventDefault();
    364     this.x1 = this.stage.getRelativePointerPosition().x;
    365     this.y1 = this.stage.getRelativePointerPosition().y;
    366     this.x2 = this.stage.getRelativePointerPosition().x;
    367     this.y2 = this.stage.getRelativePointerPosition().y;
    368 
    369     this.selectionRectangle.width(0);
    370     this.selectionRectangle.height(0);
    371     this.selecting = true;
    372   }
    373 
    374   handleMouseMove(e) {
    375     if (!this.selecting) {
    376       return;
    377     }
    378     e.evt.preventDefault();
    379     this.x2 = this.stage.getRelativePointerPosition().x;
    380     this.y2 = this.stage.getRelativePointerPosition().y;
    381 
    382     this.selectionRectangle.setAttrs({
    383       visible: true,
    384       x: Math.min(this.x1, this.x2),
    385       y: Math.min(this.y1, this.y2),
    386       width: Math.abs(this.x2 - this.x1),
    387       height: Math.abs(this.y2 - this.y1),
    388     });
    389   }
    390 
    391   handleMouseUp(e) {
    392     this.selecting = false;
    393     this.stage.draggable(false);
    394 
    395     if (!this.selectionRectangle.visible()) {
    396       return;
    397     }
    398 
    399     e.evt.preventDefault();
    400     this.selectionRectangle.visible(false);
    401     const shapes = this.stage.find(".mapObj");
    402     const box = this.selectionRectangle.getClientRect();
    403     const selected = shapes.filter((shape) => Konva.Util.haveIntersection(box, shape.getClientRect()));
    404     this.mainTransformer.nodes(selected);
    405     console.log(this.mainTransformer.nodes());
    406   }
    407 
    408   saveShapeDetails() {
    409     this.shapes.forEach((room) => {
    410       room.saveShapeDetails();
    411       console.log(room.info);
    412     });
    413   }
    414 
    415   async render() {
    416     this.saveShapeDetails();
    417     const httpService = new HttpService("http://localhost:8080/api/protected", true);
    418     try {
    419       const response = await httpService.post("/render", this.shapes);
    420       console.log(response);
    421     } catch (err) {
    422       console.log("ERROR --> Could not render map --->", err);
    423     }
    424   }
    425 
    426   async saveMap(mapName) {
    427     this.saveShapeDetails();
    428     const httpService = new HttpService("http://localhost:8080/api/protected/maps", true);
    429     try {
    430       const response = await httpService.put(`/save?mapName=${mapName}`, this.shapes);
    431       console.log(response, "resp in builder");
    432     } catch (err) {
    433       console.log("ERROR --> Could not Save map --->", err);
    434     }
    435   }
    436 
    437   handleStageClick(e) {
    438     if (this.selectionRectangle.visible()) {
    439       return;
    440     }
    441 
    442     if (e.target === this.stage) {
    443       this.mainTransformer.nodes([]);
    444       return;
    445     }
    446 
    447     if (!e.target.hasName("mapObj")) {
    448       return;
    449     }
    450 
    451     const metaPressed = e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey;
    452     const isSelected = this.mainTransformer.nodes().indexOf(e.target) >= 0;
    453 
    454     if (!metaPressed && !isSelected) {
    455       this.mainTransformer.nodes([e.target]);
    456       console.log("Sel 1");
    457     } else if (metaPressed && isSelected) {
    458       const nodes = this.mainTransformer.nodes().slice();
    459       nodes.splice(nodes.indexOf(e.target), 1);
    460       this.mainTransformer.nodes(nodes);
    461     } else if (metaPressed && !isSelected) {
    462       const nodes = this.mainTransformer.nodes().concat([e.target]);
    463       this.mainTransformer.nodes(nodes);
    464     }
    465   }
    466 
    467   addRoomType(roomType) {
    468     this.roomTypes.push(roomType);
    469   }
    470 
    471   getRoomTypes() {
    472     return this.roomTypes;
    473   }
    474 
    475   getRooms() {
    476     return this.getShapeInfoByType("Room");
    477   }
    478 
    479   getPins() {
    480     return this.getShapeInfoByType("InfoPin");
    481   }
    482 
    483   getEntrances() {
    484     return this.getShapeInfoByType("Entrance");
    485   }
    486 
    487   getConnections() {
    488     const pins = this.getShapeInfoByType("InfoPin");
    489     const entrances = this.getShapeInfoByType("Entrance");
    490     return [...pins, ...entrances];
    491   }
    492 
    493   getShapeInfoByType(type) {
    494     return this.shapes.filter((shape) => shape.className === type).map((shape) => shape.info);
    495   }
    496 
    497   updateConnections() {
    498     console.log("Update");
    499 
    500     this.shapes.forEach((shape) => {
    501       if (shape.className === "InfoPin" || shape.className === "Entrance") {
    502         shape.info.selectedPins.forEach((connectedShapeName) => {
    503           const connectedShape = this.shapes.find((s) => s.info.name === connectedShapeName);
    504           if (
    505             connectedShape &&
    506             (connectedShape.className === "InfoPin" || connectedShape.className === "Entrance")
    507           ) {
    508             if (!connectedShape.info.selectedPins.includes(shape.info.name)) {
    509               connectedShape.info.selectedPins.push(shape.info.name);
    510             }
    511           }
    512         });
    513       }
    514     });
    515   }
    516 
    517   removeConnection(from, to) {
    518     this.shapes
    519       .filter((s) => s.info.name === from || s.info.name === to)
    520       .forEach((s) => {
    521         s.info.selectedPins = s.info.selectedPins.filter((pin) => pin !== from && pin !== to);
    522       });
    523     console.log("Remove");
    524   }
    525 
    526   updateRoomNames() {
    527     this.textLayer.removeChildren();
    528     this.shapes.forEach((shape) => {
    529       shape.displayName(this.textLayer);
    530     });
    531     this.textLayer.children.forEach((child) => console.log(child));
    532   }
    533 
    534   clearMap() {
    535     this.mainLayer.removeChildren();
    536     this.shapes = [];
    537     this.hoverObj = null;
    538   }
    539 
    540   deserializeMap(data) {
    541     console.log("DESERIALIZING: ", data);
    542     this.clearMap();
    543     let dsrData = JSON.parse(data);
    544     dsrData.forEach((child) => {
    545       const shape = JSON.parse(child);
    546       const loadedShape = Factory.createShape(
    547         shape.className,
    548         { x: shape.attrs.x, y: shape.attrs.y },
    549         this.blockSize,
    550         this.mainLayer,
    551         shape.attrs.rotation,
    552           shape.attrs.scaleX,
    553           shape.attrs.scaleY
    554       );
    555       loadedShape.loadInfo(shape.attrs);
    556       this.shapes.push(loadedShape);
    557       this.addModalHandling(loadedShape);
    558       this.mainLayer.add(loadedShape);
    559     });
    560     this.mainTransformer.nodes([]);
    561     this.mainLayer.add(this.mainTransformer);
    562     this.mainLayer.add(this.selectionRectangle);
    563 
    564     this.shapes.forEach((shape) => shape.displayName(this.textLayer));
    565   }
     483            shapes: ShapeRegistry.getShapes(this.floorNum),
     484            roomTypes: JSON.stringify(this.roomTypes),
     485            mapName: this.mapName,
     486            floorNum: this.floorNum
     487        }
     488    }
     489
     490
     491    handleStageClick(e) {
     492        if (this.selectionRectangle.visible()) {
     493            return;
     494        }
     495
     496        if (e.target === this.stage) {
     497            this.mainTransformer.nodes([]);
     498            return;
     499        }
     500
     501        if (!e.target.hasName("mapObj")) {
     502            return;
     503        }
     504
     505        const metaPressed = e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey;
     506        const isSelected = this.mainTransformer.nodes().indexOf(e.target) >= 0;
     507
     508        if (!metaPressed && !isSelected) {
     509            this.mainTransformer.nodes([e.target]);
     510            console.log("Sel 1");
     511        } else if (metaPressed && isSelected) {
     512            const nodes = this.mainTransformer.nodes().slice();
     513            nodes.splice(nodes.indexOf(e.target), 1);
     514            this.mainTransformer.nodes(nodes);
     515        } else if (metaPressed && !isSelected) {
     516            const nodes = this.mainTransformer.nodes().concat([e.target]);
     517            this.mainTransformer.nodes(nodes);
     518        }
     519    }
     520
     521    addRoomType(type) {
     522        this.roomTypes.push(type);
     523    }
     524
     525    removeRoomType(targetType) {
     526        this.roomTypes = this.roomTypes.filter(type => type !== targetType);
     527    }
     528
     529    getRoomTypes() {
     530        return this.roomTypes;
     531    }
     532
     533    getRooms() {
     534        return this.getShapeInfoByType("Room");
     535    }
     536
     537    getPins() {
     538        return this.getShapeInfoByType("InfoPin");
     539    }
     540
     541    getEntrances() {
     542        return this.getShapeInfoByType("Entrance");
     543    }
     544
     545
     546
     547    getShapeInfoByType(type) {
     548        return ShapeRegistry.getShapes(this.floorNum).filter((shape) => shape.className === type).map((shape) => shape.info);
     549    }
     550
     551
     552    drawConnection(node1Name, node2Name) {
     553
     554        ShapeRegistry.drawConnection(node1Name,node2Name);
     555    }
     556
     557    getNodeByName(name) {
     558        return ShapeRegistry.getShapes(this.floorNum).filter(shape => shape instanceof MapNode && shape.info.name === name)[0];
     559    }
     560
     561    removeConnection(from, to) {
     562        ShapeRegistry.removeConnection(from,to);
     563    }
     564
     565    updateRoomNames() {
     566        this.textLayer.removeChildren();
     567        ShapeRegistry.getShapes(this.floorNum).forEach((shape) => {
     568            shape.displayName(this.textLayer);
     569        });
     570
     571    }
     572
     573    isMainEntranceSelected() {
     574        console.log(this.getEntrances().forEach((en) => console.log(en.isMainEntrance, "asdsad")));
     575
     576        let hasMainEntrance = false;
     577
     578        this.getEntrances().forEach((entrance) => {
     579            if (entrance.isMainEntrance === true) hasMainEntrance = true;
     580        });
     581
     582        return hasMainEntrance;
     583
     584    }
     585
     586    clearMap() {
     587        this.mainLayer.removeChildren();
     588        this.hoverObj = null;
     589    }
     590
     591
     592    // ova  klasa i map display da nasledbat od glavna klasa
     593
     594    loadNewFloor(floor) {
     595
     596        this._floorNum = floor?.num;
     597        let data = floor?.mapData;
     598
     599        if (data == null || data === "") return;
     600
     601        this.deserializeMap(data);
     602        shapeRegistry.getShapes(this.floorNum).forEach((shape) => {
     603            this.mainLayer.add(shape);
     604        });
     605
     606
     607    }
     608
     609    //nov
     610    deserializeMap(data) {
     611        console.log("DESERIALIZING: ", data);
     612        ShapeRegistry.clear(this.floorNum);
     613
     614        if (data != null) {
     615            const dsrData = JSON.parse(data);
     616            //load shapes
     617            dsrData.forEach((shape) => {
     618                const attrs = {
     619                    position: {x: shape.attrs.x, y: shape.attrs.y},
     620                    width: shape.attrs.width,
     621                    height: shape.attrs.height,
     622                    layer: this.mainLayer,
     623                    blockSize: this.blockSize,
     624                    rotation: shape.attrs.rotation,
     625                    scaleX: shape.attrs.scaleX,
     626                    scaleY: shape.attrs.scaleY,
     627                    increment: false,
     628                    snap: true,
     629                    fromLoad: true,
     630                    floorNum: this.floorNum
     631                };
     632
     633                const loadedShape = Factory.createShape(shape.className, attrs);
     634                loadedShape.loadInfo(shape.attrs);
     635                ShapeRegistry.add(loadedShape);
     636                // na destroy trebit events da sa trgnat
     637                addEventHandling(loadedShape, this, "dblclick");
     638            });
     639            let nodes = ShapeRegistry.getShapes(this.floorNum).filter((shape) => shape.className === "InfoPin" || shape.className === "Entrance" || shape.className === "Stairs");
     640            nodes.forEach((pin) => {
     641                let connectedPins = pin.info.selectedPins;
     642                if (connectedPins) {
     643                    connectedPins.forEach((slPin) => {
     644                        console.log("CONN node1: " + pin + "conn node2: " + slPin)
     645                        this.drawConnection(pin.info.name, slPin);
     646                    });
     647                }
     648            });
     649        }
     650
     651        this.mainTransformer.nodes([]);
     652        this.mainLayer.add(this.mainTransformer);
     653        this.mainLayer.add(this.selectionRectangle);
     654
     655        ShapeRegistry.getShapes(this.floorNum).forEach((shape) => shape.displayName(this.textLayer));
     656    }
     657
    566658}
  • imaps-frontend/src/scripts/main/MapDisplay.js

    rd565449 r0c6b92a  
    33import HttpService from "../net/HttpService.js";
    44import {zoomStage} from "../util/zoomStage.js";
     5import {addEventHandling} from "../util/addEventHandling.js";
     6import triggerNavigate from "../util/triggerNavigate.js";
     7import config from "../net/netconfig.js";
     8
    59export class MapDisplay {
    6   constructor(containerId) {
    7     this.container = document.getElementById(containerId);
    8     this.containerId = containerId;
    9     this.stage = new Konva.Stage({
    10       container: containerId,
    11       width: window.innerWidth,
    12       height: window.innerHeight,
    13       draggable: true,
    14     });
    15 
    16     this.shapes = [];
    17     this.loaded = false;
    18     this.mainLayer = new Konva.Layer();
    19     this.routeLayer = new Konva.Layer();
    20     this.textLayer = new Konva.Layer();
    21     this.stage.add(this.mainLayer);
    22     this.stage.add(this.routeLayer);
    23     this.stage.add(this.textLayer);
    24     this.route = new Konva.Line();
    25 
    26     this.stage.on("resize", () => {
    27       this.stage.width = window.innerWidth;
    28       this.stage.height = window.innerHeight;
    29     });
    30 
    31     this.stage.on("wheel",(e) => {
    32         zoomStage(e,this.stage);
    33     })
    34 
    35    
    36   }
    37 
    38   deserializeMap(data) {
    39     data.forEach((child) => {
    40         const shape = JSON.parse(child);
    41         if (shape.className !== "InfoPin") {
    42             const renderedShape = Factory.createRenderedShape(
    43                 shape.className,
    44                 shape.attrs
    45             );
    46             this.shapes.push(renderedShape);
    47       }
    48     });
    49   }
    50 
    51   displayRoomNames(){
    52     console.log("VLEZE")
    53     this.shapes.forEach(shape => {
    54       shape.displayName(this.textLayer);
    55     })
    56 
    57     this.textLayer.children.forEach(child => console.log(child,"DECAAA"));
    58   }
    59 
    60   async loadMap() {
    61     const httpService = new HttpService();
    62     const mapData = await httpService.get("/public/mapData");
    63     console.log("DESERIALIZED --->",mapData);
    64     this.deserializeMap(mapData);
    65     this.shapes.forEach((shape) => {
    66       this.mainLayer.add(shape);
    67     });
    68     this.displayRoomNames();
    69   }
    70 
    71   drawRoute(path) {
    72     this.routeLayer.removeChildren();
    73     console.log("====PATH====");
    74     path.forEach((point) => console.log(point.x, point.y));
    75 
    76     const pointsArray = path.flatMap((point) => [point.x, point.y]);
    77 
    78     console.log(pointsArray, "POINTS");
    79 
    80     let buff = [];
    81     let count = 0;
    82     let index = 0;
    83 
    84     const drawNextSegment = () => {
    85         if (index >= pointsArray.length) return;
    86 
    87         buff.push(pointsArray[index]);
    88         count++;
    89 
    90         if (count % 4 === 0) {
    91             const line = new Konva.Arrow({
    92                 points: buff,
    93                 stroke: "#e91332",
    94                 strokeWidth: 2.5,
    95                 dash: [5, 4],
    96                 lineCap: 'round',
    97                 lineJoin: 'round',
    98                 pointerLength: 7,
    99                 pointerWidth: 7,
    100                 fill:'red',
    101             });
    102 
    103             this.routeLayer.add(line);
    104             this.routeLayer.draw();
    105 
    106             console.log(buff, "BUFFER");
    107             buff = [];
    108             index -= 2;
     10    constructor(containerId, floorNum) {
     11        this.container = document.getElementById(containerId);
     12        this.containerId = containerId;
     13        this.stage = new Konva.Stage({
     14            container: containerId,
     15            width: window.innerWidth,
     16            height: window.innerHeight,
     17            draggable: true,
     18        });
     19
     20        this.shapes = [];
     21        this.roomTypes = [];
     22        this.loaded = false;
     23        this.mainLayer = new Konva.Layer();
     24        this.routeLayer = new Konva.Layer();
     25        this.textLayer = new Konva.Layer();
     26        this.stage.add(this.mainLayer);
     27        this.stage.add(this.routeLayer);
     28        this.stage.add(this.textLayer);
     29
     30        this.floorNum = floorNum;
     31
     32        this.navArrow = new Konva.Arrow({
     33            stroke: "#bb0000",
     34            strokeWidth: 3,
     35            dash: [12, 7],
     36            lineCap: "round",
     37            tension: 10,
     38            pointerLength: 2,
     39            pointerWidth: 3,
     40        });
     41
     42        this.navArrow.cache();
     43
     44        this.stage.on("resize", () => {
     45            this.stage.width = window.innerWidth;
     46            this.stage.height = window.innerHeight;
     47        });
     48
     49        this.stage.on("wheel", (e) => {
     50            zoomStage(e, this.stage);
     51        });
     52    }
     53
     54    clearMap() {
     55        this.mainLayer.removeChildren();
     56        this.shapes.forEach(shape => shape.clearText())
     57        this.shapes = [];
     58    }
     59
     60    deserializeMap(data) {
     61        this.clearMap();
     62
     63        let dsrData = JSON.parse(data);
     64        dsrData.forEach((shape) => {
     65            if (shape.className !== "InfoPin") {
     66                const renderedShape = Factory.createRenderedShape(shape.className, shape.attrs);
     67                addEventHandling(renderedShape, this, "click");
     68                this.shapes.push(renderedShape);
     69            }
     70        });
     71    }
     72
     73    displayRoomNames() {
     74        this.shapes.forEach((shape) => {
     75            shape.displayName(this.textLayer);
     76        });
     77
     78    }
     79
     80
     81
     82    loadMapN(floorData) {
     83        if (floorData == null || floorData === "") return;
     84
     85        this.deserializeMap(floorData);
     86        this.shapes.forEach((shape) => {
     87            this.mainLayer.add(shape);
     88        });
     89        this.displayRoomNames();
     90        this.initializeRoomTypes();
     91
     92    }
     93
     94    clearRoute() {
     95        this.routeLayer.removeChildren();
     96    }
     97
     98
     99    drawRouteNEW(nodes, offset = 0) {
     100
     101        this.clearRoute();
     102        console.log("====PATH====");
     103        nodes.forEach((node) => console.log("NODE", node));
     104
     105        let idx = offset;
     106        let buff = [nodes[idx].coordinates.x, nodes[idx].coordinates.y];
     107
     108
     109        ++idx;
     110
     111        console.log("INIT BUFFER", buff);
     112        console.log("INIT IDX", idx);
     113
     114        const drawNextSegment = () => {
     115
     116            if (idx >= nodes.length){
     117                return;
     118            }
     119
     120            const currentNode = nodes[idx - 1];
     121            const nextNode = nodes[idx];
     122
     123            if (nextNode.floorNumber !== currentNode.floorNumber) {
     124                triggerNavigate(nodes, idx, nextNode.floorNumber, nextNode);
     125                return;
     126            }
     127
     128            const startX = currentNode.coordinates.x;
     129            const startY = currentNode.coordinates.y;
     130            const endX = nextNode.coordinates.x;
     131            const endY = nextNode.coordinates.y;
     132
     133            const numSegments = 12;
     134
     135            const deltaX = (endX - startX) / numSegments;
     136            const deltaY = (endY - startY) / numSegments;
     137
     138            const drawSegment = (i) => {
     139                const segmentX = startX + deltaX * i;
     140                const segmentY = startY + deltaY * i;
     141
     142                buff.push(segmentX, segmentY);
     143
     144                let line = this.navArrow.clone({ points: [...buff] });
     145                this.routeLayer.add(line);
     146                this.routeLayer.draw();
     147
     148                buff = [segmentX, segmentY];
     149            };
     150
     151            let segmentIdx = 1;
     152            const interval = setInterval(() => {
     153                drawSegment(segmentIdx);
     154                segmentIdx++;
     155
     156                if (segmentIdx > numSegments) {
     157                    clearInterval(interval);
     158                    idx++;
     159                    setTimeout(drawNextSegment, 150);
     160                }
     161            }, 50);
     162        };
     163
     164        drawNextSegment();
     165    }
     166
     167
     168
     169    initializeRoomTypes() {
     170        this.roomTypes = this.shapes
     171            .filter((shape) => shape.class === "Room" && shape.info.type !== "")
     172            .map((shape) => shape.info.type);
     173    }
     174
     175    getRoomTypes() {
     176        return this.roomTypes;
     177    }
     178
     179
     180    getShapeByName(name){
     181        return this.shapes.find(shape => shape.info.name === name)
     182    }
     183
     184    getShapeByType(type) {
     185        return this.shapes.filter((shape) => shape.class === type)
     186    }
     187
     188    toggleSearchRoom() {
     189        this.toggleSearch = !this.toggleSearch;
     190    }
     191
     192    //ova e loso ne trebit vaka
     193    highlightShape(roomName) {
     194        let foundShape = this.shapes.filter((shape) => shape.info.name === roomName)[0];
     195        foundShape.highlight();
     196    }
     197
     198    getMainEntrance() {
     199        return this.shapes.filter(shape => shape.class === "Entrance").filter(el => el.info.isMainEntrance === true)[0];
     200    }
     201
     202    setFilter(filter) {
     203        let rooms = this.getShapeByType("Room")
     204        if (filter === "All") {
     205            rooms.forEach((shape) => {
     206                shape.unHighlight()
     207            })
     208        } else {
     209            rooms.filter((shape) => shape.info.type === filter).forEach((shape) => {
     210                shape.highlight()
     211            })
     212            rooms.filter((shape) => shape.info.type !== filter).forEach((shape) => {
     213                shape.unHighlight()
     214            })
    109215        }
    110216
    111         index++;
    112 
    113         setTimeout(drawNextSegment, 25);
    114     };
    115 
    116     drawNextSegment();
     217    }
    117218}
    118 
    119 
    120   search() {
    121     console.log("VLEZE VO SEARCH");
    122   }
    123 }
  • imaps-frontend/src/scripts/net/HttpService.js

    rd565449 r0c6b92a  
    33
    44class HttpService {
    5     constructor(URL = config.apiBaseUrl, auth = false) {
    6       this.baseURL = URL;
     5    constructor(auth = false) {
    76      this.auth = auth;
    87    }
     
    3332      }
    3433 
    35       const response = await fetch(`${this.baseURL}${endpoint}`, options);
     34      const response = await fetch(`${endpoint}`, options);
    3635     
    3736      if (!response.ok) {
  • imaps-frontend/src/scripts/net/netconfig.js

    rd565449 r0c6b92a  
     1export const API_BASE_URL = "http://localhost:8080/api";
     2export const API_PROTECTED = `${API_BASE_URL}/protected`
     3export const API_PUBLIC = `${API_BASE_URL}/public`
     4export const API_AUTH = `${API_BASE_URL}/auth`
     5
    16
    27const config = {
    3     apiBaseUrl: "http://localhost:8080/api",
     8    my_maps: {
     9        display: `${API_PROTECTED}/my-maps`,
     10        save: `${API_PROTECTED}/my-maps/save`,
     11        add: `${API_PROTECTED}/my-maps/create`,
     12        load: `${API_PROTECTED}/my-maps/load`,
     13        delete: `${API_PROTECTED}/my-maps/delete`,
     14        publish: `${API_PROTECTED}/publish/add`,
     15        publish_get: `${API_PROTECTED}/publish/get`,
     16    },
     17    room_types: {
     18        display: (auth) => {
     19            return auth ? `${API_PROTECTED}/room-types` : `${API_PUBLIC}/room-types`
     20        },
     21        add: `${API_PROTECTED}/room-types/add`,
    422
    5     endpoints: {
    6         login: "/auth/login",
    7         register: "/auth/register",
    8         verify: "/auth/verify",
    9         render: "/protected/render",
    10         publicMapData: "/public/mapData"
     23    },
     24    floors: {
     25        add: `${API_PROTECTED}/floors/add`,
     26        load: `${API_PROTECTED}/my-maps/load`,
     27        delete: `${API_PROTECTED}/floors/delete`,
     28    },
     29    view_maps: {
     30        display: `${API_PUBLIC}/maps`,
     31        load: (auth) => {
     32            return auth ? `${API_PROTECTED}/load-map` : `${API_PUBLIC}/load-map`
     33        },
     34        navigate: `${API_PUBLIC}/navigate`,
     35        add_favourite: `${API_PROTECTED}/favourites/add`,
     36    },
     37    favourites: {
     38        display: `${API_PROTECTED}/favourites`,
     39        add: `${API_PROTECTED}/favourites/add`,
     40        delete: `${API_PROTECTED}/favourites/delete`,
     41    },
     42    auth:{
     43        login: `${API_AUTH}/login`,
     44        register: `${API_AUTH}/register`,
     45        verify: `${API_AUTH}/verify`
     46
     47    },
     48    admin:{
     49        display: `${API_BASE_URL}/admin`,
     50        load_pr: `${API_BASE_URL}/admin/load-pr`,
     51        approve_pr: `${API_BASE_URL}/admin/pr/approve`,
     52        deny_pr: `${API_BASE_URL}/admin/pr/deny`
    1153    }
    1254};
    1355
     56
    1457export default config;
  • imaps-frontend/src/scripts/rendered_shapes/RenderedEntrance.js

    rd565449 r0c6b92a  
    1 import RenderedMapShape from "./RenderedMapShape.js";
     1import RenderedMapShape from "../base/RenderedMapShape.js";
     2import {_registerNode} from "konva/lib/Global";
     3import RenderedRoom from "./RenderedRoom.js";
    24
    3 export default class RenderedEntrance extends RenderedMapShape{
    4     constructor(attrs,scaleX,scaleY){
    5         super({
    6             x: attrs.x,
    7             y: attrs.y,
    8             width: attrs.width * scaleX,
    9             height: attrs.height * scaleY,
    10             fill: '#1c3cff',
    11             stroke: 'black',
    12             strokeWidth: 1,
    13             draggable: false,
    14             rotation: attrs.rotation,
    15             cornerRadius:3,
    16             zIndex: 0
    17         });
     5export default class RenderedEntrance extends RenderedMapShape {
     6  constructor(attrs, scaleX, scaleY) {
     7    super({
     8      x: attrs.x,
     9      y: attrs.y,
     10      width: attrs.width * scaleX,
     11      height: attrs.height * scaleY,
     12      fill: "#7fef83",
     13      stroke: "black",
     14      strokeWidth: 1,
     15      draggable: false,
     16      rotation: attrs.rotation,
     17      cornerRadius: 3,
     18      zIndex: 0,
     19    });
    1820
    19         this.info.name = attrs.obj_name;
    20         this.info.description = attrs.description;
    21        
    22    
    23         this.on("mouseenter",() => {
    24         console.log("HOVER ROOM IN", this.x());
    25         console.log(this.info.name,"NAME");
    26         this.stroke('purple');
    27         })
    28         this.on("mouseleave", () => {
    29             console.log("HOVER ROOM OUT");
    30             this.opacity(1);
    31             this.stroke('black')
     21    this.info.name = attrs.obj_name;
     22    this.info.description = attrs.description;
     23    this.info.isMainEntrance = attrs.is_main_entrance;
    3224
    33         })
     25    this.floorNum = attrs.floor_num
    3426
    35         this.initText()
    36     }
     27    this.class = "Entrance";
     28
     29    console.log("ATTRS VIEW:  " + attrs)
     30
     31    this.on("mouseenter", () => {
     32      this.stroke("purple");
     33    });
     34    this.on("mouseleave", () => {
     35      this.opacity(1);
     36      this.stroke("black");
     37    });
     38
     39    //this.initText();
     40  }
    3741}
     42
     43RenderedEntrance.prototype.className = "RenderedEntrance";
     44_registerNode(RenderedEntrance);
  • imaps-frontend/src/scripts/rendered_shapes/RenderedRoom.js

    rd565449 r0c6b92a  
    1 import RenderedMapShape from "./RenderedMapShape.js";
     1import RenderedMapShape from "../base/RenderedMapShape.js";
     2import {_registerNode} from "konva/lib/Global";
    23
    3 export default class RenderedRoom extends RenderedMapShape{
    4     constructor(attrs,scaleX,scaleY){
    5         super({
    6             x: attrs.x,
    7             y: attrs.y,
    8             width: attrs.width * scaleX,
    9             height: attrs.height * scaleY,
    10             fill: 'white',
    11             stroke: 'black',
    12             strokeWidth: 1,
    13             draggable: false,
    14             rotation: attrs.rotation,
    15             cornerRadius:3,
    16             zIndex: 0
    17         });
     4export default class RenderedRoom extends RenderedMapShape {
     5  constructor(attrs, scaleX, scaleY) {
     6    super({
     7      x: attrs.x,
     8      y: attrs.y,
     9      width: attrs.width * scaleX,
     10      height: attrs.height * scaleY,
     11      fill: "#A2D9FF",
     12      stroke: "black",
     13      strokeWidth: 1,
     14      draggable: false,
     15      rotation: attrs.rotation,
     16      cornerRadius: 3
     17    });
    1818
    19         this.info.name = attrs.obj_name;
    20         this.info.description = attrs.description;
     19    console.info("FNUM RENDER:",attrs.floor_num)
    2120
    22         this.textOffsetX = -50
    23        
    24    
    25         this.on("mouseenter",() => {
    26         console.log("HOVER ROOM IN", this.x());
    27         console.log(this.info.name,"NAME");
    28         this.opacity(0.7);
    29         this.fill("pink");
    30         })
    31         this.on("mouseleave", () => {
    32             console.log("HOVER ROOM OUT");
    33             this.opacity(1);
    34             this.fill("white");
    35         })
     21    this.floorNum = attrs.floor_num
    3622
    37         this.initText()
    38     }
     23    this.info.name = attrs.obj_name;
     24    this.info.type = attrs.room_type;
     25    this.info.description = attrs.description;
     26    this.class = "Room";
     27    this.textOffsetX = -50;
    3928
    40    
     29    this.eventName = "openRoomInfoPanel"
     30
     31    this.on("mouseenter", () => {
     32      console.log(this.info.name, "NAME");
     33      this.fill("#65c3f8");
     34    });
     35    this.on("mouseleave", () => {
     36      this.fill("#A2D9FF");
     37    });
     38
     39
     40
     41    // searched(){
     42    //   this.fill("#b92d39")
     43    // }
     44    // unsearched(){
     45    //   this.fill("#A2D9FF");
     46    // }
     47
     48    // console.log("ATTRS: " + attrs);
     49
     50    this.initText();
     51  }
     52  highlight(){
     53    this.fill("rgba(29,238,78,0.49)");
     54    this.strokeWidth(2)
     55  }
     56  unHighlight(){
     57    this.fill("#A2D9FF");
     58    this.strokeWidth(1);
     59  }
    4160}
     61RenderedRoom.prototype.className = "RenderedRoom";
     62_registerNode(RenderedRoom);
  • imaps-frontend/src/scripts/rendered_shapes/RenderedWall.js

    rd565449 r0c6b92a  
    1 import RenderedMapShape from "./RenderedMapShape.js";
     1import RenderedMapShape from "../base/RenderedMapShape.js";
     2import {_registerNode} from "konva/lib/Global";
    23
    34export default class RenderedWall extends RenderedMapShape{
     
    89            width: attrs.width * scaleX,
    910            height: attrs.height * scaleY,
    10             fill: 'grey',
     11            fill: '#4B4B4B',
    1112            stroke: 'black',
    1213            strokeWidth: 1,
     
    1819    }
    1920}
     21
     22RenderedWall.prototype.className = "RenderedWall";
     23_registerNode(RenderedWall);
  • imaps-frontend/src/scripts/shapes/Entrance.js

    rd565449 r0c6b92a  
    1 import Konva from "konva";
    2 import MapShape from "./MapShape";
    3 import { _registerNode } from "konva/lib/Global";
    4 export default class Entrance extends MapShape {
    5   constructor(mousePos, blockSize, layer, rotation, snap,id,scaleX = 1, scaleY = 1) {
    6     super(
    7       {
    8         x: mousePos.x,
    9         y: mousePos.y,
    10         width: blockSize * scaleX,
    11         height: blockSize * 2 * scaleY,
    12         fill: "#0051ff",
    13         stroke: "grey",
    14         strokeWidth: 1,
    15         opacity: 0.7,
    16         name: "mapObj",
    17         draggable: true,
    18         rotation: rotation,
    19         zIndex: 1,
    20       },
    21       layer,
    22       blockSize,
    23       snap
    24     );
    25     this.type = "Entrance";
    26     this.modalEventName = "openEntranceModalEvent";
     1import {_registerNode} from "konva/lib/Global";
     2import MapNode from "../base/MapNode.js";
     3import {node} from "prop-types";
    274
    28     this.id = id;
     5export default class Entrance extends MapNode {
    296
    30     this._info = {
    31       name: `Entrance ${id}`,
    32       connectedRoom: "",
    33       description: "",
    34       isMainEntrance: false,
    35       selectedPin: "",
    36       selectedPins: [],
    37     };
     7    constructor(attrs, id) {
    388
    39     this.initText();
    40   }
     9        if (!attrs.fromLoad) {
     10            attrs.height *= 2;
     11        }
     12        super(
     13            {
     14                x: attrs.position.x,
     15                y: attrs.position.y,
     16                width: attrs.width,
     17                height: attrs.height,
     18                fill: "rgb(126,238,167)",
     19                stroke: "#252627",
     20                strokeWidth: 1,
     21                opacity: 0.9,
     22                name: "mapObj",
     23                draggable: true,
     24                rotation: attrs.rotation,
     25                zIndex: 1,
     26            },
     27            attrs.layer,
     28            attrs.blockSize,
     29            attrs.snap
     30        );
     31        this.type = "Entrance";
     32        this.eventName = "openEntranceModalEvent";
     33        this.floorNum = attrs.floorNum
    4134
    42   loadInfo(attrs) {
    43     this.info.name = attrs.obj_name;
    44     this.info.connectedRoom = attrs.connected_room;
    45     this.info.description = attrs.description;
    46     this.info.isMainEntrance = attrs.is_main_entrance;
    47     this.info.selectedPins = attrs.connected_pins;
    48   }
     35        this.id = id;
    4936
    50   saveShapeDetails() {
    51     this.setAttr("connected_pins", this.info.selectedPins);
    52     this.setAttr("obj_name", this.info.name);
    53     this.setAttr("description", this.info.description);
    54     this.setAttr("is_main_entrance", this.info.isMainEntrance);
    55     this.setAttr("connected_room", this.info.connectedRoom);
    56   }
     37        this._info = {
     38            name: `Entrance${id} [${this.floorNum}F]`,
     39            connectedRoom: "",
     40            description: "",
     41            isMainEntrance: false,
     42            selectedPin: "",
     43            selectedPins: [],
     44        };
     45
     46        this.initText();
     47        this.moveToTop();
     48    }
     49
     50    loadInfo(attrs) {
     51        this.info.name = attrs.obj_name;
     52        this.info.connectedRoom = attrs.connected_room;
     53        this.info.description = attrs.description;
     54        this.info.isMainEntrance = attrs.is_main_entrance;
     55        this.info.selectedPins = attrs.connected_pins;
     56        this.floorNum = attrs.floor_num;
     57    }
     58
     59    saveShapeDetails() {
     60        console.info("fnum entrance",this.attrs.floorNum)
     61
     62        this.setAttr("connected_pins", this.info.selectedPins);
     63        this.setAttr("obj_name", this.info.name);
     64        this.setAttr("description", this.info.description);
     65        this.setAttr("is_main_entrance", this.info.isMainEntrance);
     66        this.setAttr("connected_room", this.info.connectedRoom);
     67        this.setAttr("floor_num",this.floorNum);
     68    }
     69
     70    connect(node, draw = true) {
     71        if(this.floorNum !== node.floorNum) return;
     72
     73        super.connect(node)
     74    }
     75
     76    setInfo(infoObj) {
     77        console.log("SA VIKNA SETINFO")
     78        this.info = infoObj;
     79        if(this.info.connectedRoom == null || this.info.connectedRoom === "" ){
     80            this.strokeWidth(2);
     81            this.stroke("#a10114")
     82        }else{
     83            this.strokeWidth(1)
     84            this.stroke("black")
     85        }
     86    }
    5787}
    5888
  • imaps-frontend/src/scripts/shapes/InfoPin.js

    rd565449 r0c6b92a  
    1 import Konva from "konva";
    2 import MapShape from "./MapShape";
    3 import Factory from "../util/Factory";
     1
    42import { _registerNode } from "konva/lib/Global";
    5 export default class InfoPin extends MapShape {
    6   constructor(mousePos, blockSize, layer, snappable,id) {
     3import MapNode from "../base/MapNode.js";
     4import {node} from "prop-types";
     5import draw from "../../pages/Draw/Draw.jsx";
     6export default class InfoPin extends MapNode {
     7  constructor(attrs,id) {
     8    attrs.snap = false;
    79    super(
    810      {
    9         x: mousePos.x,
    10         y: mousePos.y,
    11         radiusX: blockSize * 0.5,
    12         radiusY: blockSize * 0.7,
    13         tailHeight: blockSize * 1.2,
    14         fill: "#d70113",
     11        x: attrs.position.x,
     12        y: attrs.position.y,
     13        radiusX: attrs.blockSize * 0.5,
     14        radiusY: attrs.blockSize * 0.7,
     15        tailHeight: attrs.blockSize * 1.2,
     16        fill: "#f60000",
    1517        stroke: "#1b1b1b",
    16         strokeWidth: 0.2,
     18        strokeWidth: 1,
    1719        draggable: true,
    1820        name: "mapObj",
    1921      },
    20       layer,
    21       blockSize,
    22       snappable
     22      attrs.layer,
     23      attrs.blockSize,
     24      attrs.snap
    2325    );
    2426
    2527    this.id = id;
     28    this.eventName = "openPinModalEvent";
     29    this.floorNum = attrs.floorNum;
    2630
    27     this.modalEventName = "openPinModalEvent";
    2831    this.type = "InfoPin";
    2932    this._info = {
    30       name: `Pin ${id}`,
     33      name: `Pin${id} [${this.floorNum}F]`,
    3134      selectedPins: [],
    3235      description: "",
     
    3437
    3538    this.on("mouseover", () => {
    36       this.fill("yellow");
     39      this.fill("#FFD700");
    3740    });
    3841    this.on("mouseout", () => {
    39       this.fill("red");
     42      this.fill("#f60000");
    4043    });
     44
    4145
    4246    this.initText();
    4347  }
    4448  _sceneFunc(context, shape) {
    45     const { radiusX, radiusY, tailHeight } = this.attrs;
     49    const { radiusX, radiusY, tailHeight } = this.attrs; // attrs od konva
    4650
    4751    context.beginPath();
     
    5963  }
    6064
     65
    6166  loadInfo(attrs) {
    6267    this.info.name = attrs.obj_name;
    6368    this.info.selectedPins = attrs.connected_pins;
    6469    this.info.description = attrs.description;
     70    this.floorNum = attrs.floor_num
    6571  }
    6672
     
    6975    this.setAttr("connected_pins", this.info.selectedPins);
    7076    this.setAttr("description", this.info.description);
     77    this.setAttr("floor_num",this.floorNum)
    7178    console.log(this.info, "vnatre vo info");
     79  }
     80
     81  connect(node, draw = true) {
     82    if(this.floorNum !== node.floorNum) return;
     83    super.connect(node)
    7284  }
    7385}
  • imaps-frontend/src/scripts/shapes/Room.js

    rd565449 r0c6b92a  
    11import Konva from "konva";
    2 import MapShape from "./MapShape";
     2import MapShape from "../base/MapShape.js";
    33import { _registerNode } from "konva/lib/Global";
    44export default class Room extends MapShape {
    5   constructor(mousePos, blockSize, layer, rotation, snap, id, scaleX = 1, scaleY = 1){
     5  constructor(attrs,id){
     6
     7      if(!attrs.fromLoad){
     8          attrs.width *= 12;
     9          attrs.height *= 8;
     10      }
     11
     12      console.log(attrs.position,"hehe")
    613    super(
    714      {
    8         x: mousePos.x,
    9         y: mousePos.y,
    10         width: blockSize * 8 * scaleX,
    11         height: blockSize * 4 * scaleY,
    12         fill: "#DDE0F8",
     15        x: attrs.position.x,
     16        y: attrs.position.y,
     17        width: attrs.width * attrs.scaleX,
     18        height: attrs.height * attrs.scaleY,
     19        fill: "rgb(86,168,253)",
    1320        stroke: "grey",
    1421        strokeWidth: 1,
    1522        name: "mapObj",
    16         rotation: rotation,
     23        rotation: attrs.rotation,
    1724        draggable: true,
    1825      },
    19       layer,
    20       blockSize,
    21       snap
     26        attrs.layer,
     27        attrs.blockSize,
     28        attrs.snap
    2229    );
    2330
     31      this.floorNum = attrs.floorNum;
     32
    2433    this._info = {
    25       name: `Room ${id}`,
     34      name: `Room${id} [${this.floorNum}F]`,
    2635      type: "",
    2736      description: "",
     
    2938
    3039    this.type = "Room";
    31     this.modalEventName = "openRoomModalEvent";
     40    this.eventName = "openRoomModalEvent";
    3241    this.id = id;
    3342
     
    3948    this.info.type = attrs.room_type;
    4049    this.info.description = attrs.description;
     50    this.floorNum = attrs.floor_num;
    4151  }
    4252
     
    4555    this.setAttr("room_type", this.info.type);
    4656    this.setAttr("description", this.info.description);
     57    this.setAttr("floor_num",this.floorNum);
    4758  }
    4859}
  • imaps-frontend/src/scripts/shapes/Stairs.js

    rd565449 r0c6b92a  
    11import Konva from "konva";
    2 import { MapShape } from "./MapShape";
     2import MapNode from "../base/MapNode.js";
     3import {_registerNode} from "konva/lib/Global.js";
     4import Room from "./Room.js";
     5export default class Stairs extends MapNode{
     6    constructor(attrs,id) {
    37
     8        if(!attrs.fromLoad){
     9            attrs.width *= 4;
     10        }
     11
     12        super({
     13                x: attrs.position.x,
     14                y: attrs.position.y,
     15                width: attrs.width * attrs.scaleX,
     16                height: attrs.height * attrs.scaleY,
     17                fill: "rgb(225,213,124)",
     18                stroke: "rgb(16,15,15)",
     19                strokeWidth: 1,
     20                name: "mapObj",
     21                rotation: attrs.rotation,
     22                draggable: true
     23            },
     24            attrs.layer,
     25            attrs.blockSize,
     26            attrs.snap
     27        );
     28
     29        this.floorNum = attrs.floorNum;
     30
     31        this.type = "Stairs"
     32        this._info = {
     33            name: `Stairs${id} [${this.floorNum}F]`,
     34            description: "",
     35            selectedPins: []
     36        };
     37
     38        this.id = id;
     39        this.eventName = "openStairsModalEvent";
     40        this.initText();
     41    }
     42
     43
     44    _sceneFunc(context, shape) {
     45        const { width, height} = this.attrs;
     46
     47        let steps = 5;
     48        context.beginPath()
     49        for(let i = 0; i < steps; i++){
     50            context.rect((-this.blockSize) * i,(this.blockSize * 0.6) * i,width * 0.86,height/2)
     51            context.fillStrokeShape(shape);
     52        }
     53        context.closePath()
     54    }
     55
     56    loadInfo(attrs) {
     57        this.info.name = attrs.obj_name;
     58        this.info.description = attrs.description;
     59        this.info.selectedPins = attrs.connected_pins;
     60        this.floorNum = attrs.floor_num;
     61    }
     62
     63    saveShapeDetails() {
     64        this.setAttr("connected_pins", this.info.selectedPins);
     65        this.setAttr("obj_name", this.info.name);
     66        this.setAttr("description", this.info.description);
     67        this.setAttr("floor_num",this.floorNum)
     68    }
     69    connect(node,draw = true) {
     70        let canDraw = this.floorNum === node.floorNum;
     71        super.connect(node,canDraw);
     72    }
     73
     74}
     75
     76Stairs.prototype.className = "Stairs";
     77_registerNode(Stairs);
    478//TODO
  • imaps-frontend/src/scripts/shapes/Wall.js

    rd565449 r0c6b92a  
    11import Konva from "konva";
    2 import MapShape from "./MapShape";
     2import MapShape from "../base/MapShape.js";
    33import { _registerNode } from 'konva/lib/Global';
    44export default class Wall extends MapShape {
    5     constructor(mousePos, blockSize, layer, rotation,snap, draggable = true,scaleX = 1, scaleY = 1){
     5    constructor(attrs){
     6        if(!attrs.fromLoad){
     7            attrs.height *= 8;
     8        }
     9
     10
    611      super(
    712        {
    8           x: mousePos.x,
    9           y: mousePos.y,
    10           width: blockSize * scaleX,
    11           height: blockSize * 8 * scaleY,
    12           fill: "#DDE0F8",
     13          x: attrs.position.x,
     14          y: attrs.position.y,
     15          width: attrs.width * attrs.scaleX,
     16          height: attrs.height * attrs.scaleY,
     17          fill: "#d3d3d3",
    1318          stroke: "grey",
    1419          strokeWidth: 1,
    1520          name: "mapObj",
    16           draggable: draggable,
    17           rotation: rotation,
     21          draggable: true,
     22          rotation: attrs.rotation,
    1823          zIndex: 0,
    1924        },
    20         layer,
    21         blockSize,
    22         snap,
     25        attrs.layer,
     26        attrs.blockSize,
     27        attrs.snap,
    2328      );
    24  
    2529      this.type = "Wall";
     30
     31        this.floorNum = attrs.floorNum;
    2632    }
    27   }
     33
     34    loadInfo(attrs) {
     35        this.floorNum = attrs.floor_num;
     36    }
     37
     38    saveShapeDetails() {
     39        this.setAttr("floor_num",this.floorNum)
     40    }
     41}
    2842
    2943  Wall.prototype.className = 'Wall'
  • imaps-frontend/src/scripts/util/Factory.js

    rd565449 r0c6b92a  
    66import RenderedEntrance from "../rendered_shapes/RenderedEntrance";
    77import RenderedWall from "../rendered_shapes/RenderedWall.js";
     8import Stairs from "../shapes/Stairs.js";
     9import RenderedStairs from "../rendered_shapes/RenderedStairs.js";
     10import {updateShapeCount, getShapeCount} from "./ShapeCount.js";
    811export default class Factory {
     12  // BUG KO KE NAPRES REFRESH SA RESETVAT COUNTS!
    913
    10   static infoPinCount = 0;
    11   static wallCount = 0;
    12   static entranceCount = 0;
    13   static roomCount = 0;
     14  static createShape(shapeType,attrs) {
     15    console.log(attrs,"attrs in factory")
     16    console.log("position in factory: " + attrs.position.x)
    1417
    15   static createShape(shapeType, position, blockSize, layer, rotation,scaleX = 1, scaleY = 1, increment = false) {
     18    let scaleX = (attrs.scaleX ? parseFloat(attrs.scaleX) : 1);
     19    let scaleY =  (attrs.scaleY ? parseFloat(attrs.scaleY) : 1);
     20
     21    attrs.scaleX = scaleX;
     22    attrs.scaleY = scaleY;
     23
    1624    switch (shapeType) {
    1725      case "Entrance":
    18         if(increment) this.entranceCount++;
    19         return new Entrance(position, blockSize, layer, rotation,true,this.entranceCount,scaleX,scaleY);
     26        if(attrs.increment) updateShapeCount("entrance")
     27        return new Entrance(attrs,getShapeCount("entrance"));
    2028      case "Room":
    21         if(increment) this.roomCount++;
    22         return new Room(position, blockSize, layer, rotation,true, this.roomCount,scaleX,scaleY);
    23       case "Wall":
    24         return new Wall(position, blockSize, layer, rotation,true,scaleX,scaleY);
    25       case "InfoPin":
    26         if(increment) this.infoPinCount++;
    27         return new InfoPin(position, blockSize, layer, false,this.infoPinCount);
     29        if(attrs.increment) updateShapeCount("room");
     30        return new Room(attrs,getShapeCount("room"));
     31       case "Wall":
     32         return new Wall(attrs);
     33       case "InfoPin":
     34        if(attrs.increment) updateShapeCount("infoPin")
     35          return new InfoPin(attrs,getShapeCount("infoPin"));
     36      case "Stairs":
     37        if(attrs.increment) updateShapeCount("stairs")
     38        return new Stairs(attrs,getShapeCount("stairs"))
    2839      default:
    2940        throw new Error("Invalid shape type: " + shapeType);
     
    4152      case "Wall":
    4253        return new RenderedWall(attrs,scaleX,scaleY);
     54      case "Stairs":
     55        return new RenderedStairs(attrs,scaleX,scaleY)
    4356      default:
    4457        throw new Error("Invalid shape type." + shapeType);
  • imaps-frontend/src/scripts/util/zoomStage.js

    rd565449 r0c6b92a  
    1 export const zoomStage = (e,stage) => {
    2     if (!e.evt.shiftKey) return;
     1export const zoomStage = (e,stage,shift=false) => {
     2    if (shift && !e.evt.shiftKey) return;
    33
    44    e.evt.preventDefault();
Note: See TracChangeset for help on using the changeset viewer.