Skip to content

Commit

Permalink
7.1 better canvas download && added screen recording
Browse files Browse the repository at this point in the history
  • Loading branch information
MizaGBF committed Nov 22, 2024
1 parent f3c82d0 commit e68ae61
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 36 deletions.
Binary file added assets/ui/controls/record.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ select:hover {
z-index:100;
text-align: center;
font-size: 25px;
width: 12em;
width: 15em;
color: #ffffff;
align-items: center;
}
Expand Down
6 changes: 3 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<body onload="init()">
<a href="index.html"><img id="titleheader" src="assets/ui/header.png" alt="header"></a>
<div id="header">
<div>v7.0</div>
<div>v7.1</div>
<div id="timestamp"></div>
</div>
<div id="issues" style="display:none">
Expand Down Expand Up @@ -85,8 +85,8 @@ <h3>&#x2022; Keyboard shortcuts</h3>
<li><b>D</b> to update and download the canvas.</li>
</ul>
</p>
<h3>&#x2022; The download button doesn't work</h3>
<p>Sometimes, the resulting image from using the download button is uncomplete or just plain wrong. There is nothing I can do about it, at first glance. It if persits, you can use Right click > Save as on PC instead, the result should be perfect.</p>
<h3>&#x2022; The resulting image from the download button is weird...</h3>
<p>The download button saves the whole canvas, including what's "off-screen". This is the same result as when doing Right Click > Save as.</p>
<h3>&#x2022; Class Champion weapons seem to be bugged</h3>
<p>For those weapon series, and similar other series, use the first version of the weapon (usually the Fire one) to view the full animations.</p>
<h3>&#x2022; Restrictions</h3>
Expand Down
83 changes: 57 additions & 26 deletions player.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,14 @@ function setHTML()
<div class="controls-outline">\
<input id="speed-input" type="range" min="0.05" max="2" step="0.05" value="1" oninput="changeSpeed(this);">\
<label id="speed-label" for="speed-input" class="controls-text">100% Speed</label><br>\
<button class="small-button" onclick="let elem = document.getElementById(\'speed-input\'); elem.value=\'1\'; changeSpeed(elem);"><img src="assets/ui/controls/reset.png"></button>\
<button class="small-button" onclick="resetSpeed();"><img src="assets/ui/controls/reset.png"></button>\
<button class="small-button" onclick="togglePause();" id="pause-btn"><img src="assets/ui/controls/pause.png"></button>\
<button class="small-button" onclick="nextframe();" id="next-btn"><img src="assets/ui/controls/next.png"></button>\
<button class="small-button btn-enabled" onclick="toggleLoop();" id="loop-btn"><img src="assets/ui/controls/loop.png"></button>\
<button class="small-button" onclick="toggleSFX();" id="sfx-btn"><img src="assets/ui/controls/sfx.png"></button>\
<button class="small-button" onclick="openCustom()")"><img src="assets/ui/controls/edit.png"></button>\
<button class="small-button" onclick="dlimage();" id="dl-btn"><img src="assets/ui/controls/dl.png"></button>\
<button class="small-button" onclick="record();" id="record-btn"><img src="assets/ui/controls/record.png"></button>\
</div>\
<div class="controls-outline">\
<span class="controls-text">Background</span><br>\
Expand Down Expand Up @@ -127,10 +128,19 @@ function setHTML()
document.getElementById("canvas-container").scrollIntoView();
}

function openCustom()
function canInteract()
{
// check if it loaded
let name = document.getElementById("act-name");
if(name == null || name.getElementsByTagName('img').length > 0) return;
if(name == null || name.getElementsByTagName('img').length > 0) return false;
// check if it's recording
if(this.cjsViewList[animeVersion].recording != null) return false;
return true;
}

function openCustom()
{
if(!canInteract()) return;
let cact = document.getElementById("custom-action");
if(cact.style.display == "") return;
beep();
Expand Down Expand Up @@ -208,8 +218,7 @@ function updateDemoList()

function actionChange(obj)
{
let name = document.getElementById("act-name");
if(name == null || name.getElementsByTagName('img').length > 0) return;
if(!canInteract()) return;
beep();
var action = obj.options[obj.selectedIndex].value;
if (action == 'default')
Expand Down Expand Up @@ -246,17 +255,12 @@ document.addEventListener("keydown", spacekey_fix);

function keybind_listener(event)
{
let name = document.getElementById("act-name");
if(name == null || name.getElementsByTagName('img').length > 0) return;
// return until loading is complete

if(!canInteract()) return;
switch(event.code)
{
case "KeyR": // speed reset
{
let elem = document.getElementById('speed-input');
elem.value="1";
changeSpeed(elem);
resetSpeed();
return;
}
case "NumpadAdd": // speed up
Expand Down Expand Up @@ -316,8 +320,7 @@ document.addEventListener("keyup", keybind_listener);

function togglePause()
{
let name = document.getElementById("act-name");
if(name == null || name.getElementsByTagName('img').length > 0) return;
if(!canInteract()) return;
beep();
if(this.cjsViewList[animeVersion].isPaused)
{
Expand All @@ -333,8 +336,7 @@ function togglePause()

function toggleLoop()
{
let name = document.getElementById("act-name");
if(name == null || name.getElementsByTagName('img').length > 0) return;
if(!canInteract()) return;
beep();
let loop_btn = document.getElementById("loop-btn");
if(loop_btn.classList.contains('btn-enabled'))
Expand All @@ -351,10 +353,21 @@ function toggleLoop()
this.cjsViewList[animeVersion].loopPaused = !loopingState;
}

function enableLoop()
{
let loop_btn = document.getElementById("loop-btn");
if(!loop_btn.classList.contains('btn-enabled'))
{
loop_btn.classList.add("btn-enabled");
loopingState = true;
this.cjsViewList[animeVersion].nextLoop();
this.cjsViewList[animeVersion].loopPaused = !loopingState;
}
}

function toggleSFX()
{
let name = document.getElementById("act-name");
if(name == null || name.getElementsByTagName('img').length > 0) return;
if(!canInteract()) return;
beep();
let sfx_btn = document.getElementById("sfx-btn");
if(sfx_btn.classList.contains('btn-enabled'))
Expand All @@ -371,35 +384,53 @@ function toggleSFX()

function changeSpeed(elem)
{
let name = document.getElementById("act-name");
if(name == null || name.getElementsByTagName('img').length > 0) return;
if(!canInteract())
{
elem.value = JSON.stringify(action_speed);
return;
}
action_speed = parseFloat(elem.value);
createjs.Ticker.framerate = 30*action_speed;
document.getElementById("speed-label").innerHTML = JSON.stringify(Math.floor(100*action_speed)) + "% Speed";
}

function resetSpeed()
{
let elem = document.getElementById('speed-input');
elem.value='1';
changeSpeed(elem);
}

function nextframe()
{
let name = document.getElementById("act-name");
if(name == null || name.getElementsByTagName('img').length > 0) return;
if(!canInteract()) return;
if(!this.cjsViewList[animeVersion].isPaused) togglePause();
else beep();
this.cjsViewList[animeVersion].nextFrame();
}

function dlimage()
{
let name = document.getElementById("act-name");
if(name == null || name.getElementsByTagName('img').length > 0) return;
if(!canInteract()) return;
if(!this.cjsViewList[animeVersion].isPaused) togglePause();
else beep();
this.cjsViewList[animeVersion].download();
}

function record()
{
if(!canInteract()) return;
if(!this.cjsViewList[animeVersion].isPaused) togglePause();
else beep();
resetSpeed();
enableLoop();
// start recording
this.cjsViewList[animeVersion].record();
}

function versionChange(obj)
{
let name = document.getElementById("act-name");
if(name == null || name.getElementsByTagName('img').length > 0) return;
if(!canInteract()) return;
beep();

animeVersion = obj.options[obj.selectedIndex].value;
Expand Down
80 changes: 74 additions & 6 deletions view/cjs_npc_demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ define(["view/cjs", "view/content", "lib/common"], function (cjsview, content) {
damageTarget: null,
loopIndex: null,
npc: null,
recording: null,
initialize: function(params) // constructor
{
params = params || {};
Expand Down Expand Up @@ -889,17 +890,84 @@ define(["view/cjs", "view/content", "lib/common"], function (cjsview, content) {
download : function() { // update the animation and download the canvas content. Must be paused beforehand.
if(this.isPaused)
{
this.stage.update();
this.stage.canvas.toBlob((blob) => {
const url = URL.createObjectURL(blob);
let url = this.stage.toDataURL("image/png");
if(url)
{
let link = document.createElement('a');
link.href = url;
link.download = 'gbfap_' + Date.now() + '.png';
link.click();
URL.revokeObjectURL(url);
pushPopup("Image saved to " + link.download);
}, "image/png");
pushPopup("Image saved as " + link.download);
}
}
},
record : function() { // record a webm of the current animation. Must be paused beforehand.
if(this.isPaused)
{
try
{
// restart current animation
this.reset();
// container
this.recording = {this: this, position: 0, frames: 0, canvas: null, ctx: null, stream: null, rec: null, chunks: []};
// create a canvas on which we'll draw
this.recording.canvas = document.createElement("canvas");
this.recording.canvas.width = WINDOWSIZE;
this.recording.canvas.height = WINDOWSIZE;
this.recording.ctx = this.recording.canvas.getContext("2d");
// set to 0 fps to disable automatic capture
this.recording.stream = this.recording.canvas.captureStream(0);
// create and set media recorder
this.recording.rec = new MediaRecorder(this.recording.stream, {videoBitsPerSecond:50*1024*1024}); // 50mbps
this.recording.rec.ondataavailable = e => this.recording.chunks.push(e.data);
const myself = this;
this.recording.rec.onstop = e => function() {
let blob = new Blob(myself.recording.chunks, {type: 'video/webm'});
let url = URL.createObjectURL(blob);
let link = document.createElement('a');
link.href = url;
link.download = 'gbfap_' + Date.now() + '.webm';
link.click();
pushPopup("Video saved as " + link.download);
URL.revokeObjectURL(url)
myself.recording = null;
}();
// start (using 1s chunks)
this.recording.rec.start(1);
// note current position
this.recording.position = this.animChanger.position;
// send popup to user
pushPopup("Creating the video, be patient...");
// resume animation and wait next frame
this.resume();
setTimeout(this.record_next_frame, 1, this.recording);
}
catch(err) // error handling
{
this.recording = null;
this.pause();
console.error("Exception thrown", err.stack);
pushPopup("An error occured. This feature might be unavailable on your device.");
}
}
},
record_next_frame : function(recording) { // on next frame
if(recording.position != recording.this.animChanger.position) // check if the frame changed
{
recording.position = recording.this.animChanger.position; // update position
recording.this.pause(); // pause animation
if(recording.this.animChanger.position == 0 && recording.frames > 0) // check if we did a whole loop
{
recording.rec.stop(); // stop if so
return;
}
recording.ctx.clearRect(0,0,WINDOWSIZE,WINDOWSIZE); // clear canvas
recording.ctx.drawImage(recording.this.stage.canvas,(CANVAS_SIZE-WINDOWSIZE)/2,(CANVAS_SIZE-WINDOWSIZE)/2,WINDOWSIZE,WINDOWSIZE,0,0,WINDOWSIZE,WINDOWSIZE); // crop stage canvas to our canvas
recording.stream.getVideoTracks()[0].requestFrame(); // request frame
recording.frames++;
recording.this.resume(); // resume animation
}
setTimeout(recording.this.record_next_frame, 1, recording); // wait next frame
},
reset : function() { // restart the current animation
// used as a workaround for a weird bug causing images to not display on the first animation played.
Expand Down

0 comments on commit e68ae61

Please sign in to comment.