JSFiddle - React, Tailwind, and code Playground

by Gwyn Milcote

HTML

figuring out cutscenes.

<div id='container'>



    <div id='timeline-container'>
    
        <!-- Image with range of seconds, in 10ths -->
        <canvas id='timeline-scale'></canvas>
        
        <!-- css positioned divs, in layers? -->
        <div id='timeline-commands'></div>
        
        <div id='timeline-bar'></div>
    
    </div>

</div>

CSS

div, img, canvas, input, select, button {
    box-sizing: border-box;
}

#container {
    width: 970px;
    margin: 30px auto;
}

/*
* Import, export JSON. Later load files?
*/
#top-menu {}

/**/
#main-container {
    display: flex;
    
}

/*
* Contains canvas where cutscene plays.
*/
#scene-container {
    width: 720px;
    background-color: darkgray;
}

/*
* Panel for editing commands in timeline.
*/
#sidebar-container {
    width: 250px;
    background-color: #eee;
}

/*
* ...
*/
#timeline-container {
    position: relative;
}

/* Canvas that lists seconds. */
#timeline-scale {
    width: 970px;
    height: 40px;
}

/* Horizontal stacked layers of events. */
#timeline-commands {
    position: relative;
    background-color: darkgray;
    overflow: auto;
    height: 200px;
}
#timeline-commands .command {
    position: absolute;
    height: 30px;
    background-color: lightgreen;
    border: 1px solid green;
    display: flex;
    justify-content: space-between;
}
#timeline-commands .command:hover {
    cursor: pointer;
}
#timeline-commands .selected-command {
    background-color: #fff !important;
}
#timeline-commands .command .resize-command {
    width: 8px;
    cursor: w-resize;
}

/* Vertical bar that indicates current time. */
#timeline-bar {
    z-index: 2;
    position: absolute;
    top: 0;
    height: 200px;
    width: 1px;
    background-color: red;
}

JavaScript

let cutsceneData = {

    assets: {
        mesh: ["table", "cube", "rectangle", "tree"],
        material: ["wood", "wall_stone", "grass", "tree_pine", "knight", "dragon_green", "skybox_dusk"],
        sound: ["castle_bgm", "forest_bgm", "dragon_roar"]
    },

    scenes: [
        {
            id: 1, name: "Castle", 
            camera: {
                mode: "orthogonal",
                pos: {x: 6, y: 7, z: 3},
                rot: {x: 6, y: 7, z: 3}
            },
            entities: [
                {id: 1, name: "Wooden table", mesh: "table", material: "wood"},
                {id: 2, name: "Knight", mesh: "cube", material: "knight"},
                {id: 3, name: "Dragon", mesh: "rectangle", material: "dragon_green"}
            ],
            
        },{
            id: 2, name: "Forest",
            mist: {
                distance: 3, colour: "CCCCCC"
            },
            skybox: {
                material: "skybox_dusk", size: 5
            },
            camera: {
                mode: "perspective",
                pos: {x: 6, y: 7, z: 3},
                rot: {x: 6, y: 7, z: 3}
            }
            
        }
    ],
    
    timeline: [
        {scene: 1, action: "camera", start: 1.05, end: 1.55},
        {scene: 1, entity: 1, action: "", start: 1.05, end: 1.55},
        {scene: 1, entity: 1, action: "", start: 1.05, end: 1.55}
    ]
    
};


class CutsceneEditor {

    constructor(){
        // Milliseconds in 1 visual second?
        this.timeScale = 60; 
        // Move horizontal scrollbar.
        this.timeStart = 0;
        // Exact time selected or being played now.
        this.currentTime = 0;
    
        // Display the current range of seconds.
        this.tCanvas = document.getElementById("timeline-scale");
        this.tCtx = this.tCanvas.getContext("2d");
        this.tCanvas.width = 970;
        this.tCanvas.height = 40;
        
        // Demo data.
        this.commands = [
            {id: 1, name: "test 1",...