mirror of
https://github.com/eliasstepanik/vdo.ninja.git
synced 2026-01-13 14:48:31 +00:00
2397 lines
83 KiB
HTML
2397 lines
83 KiB
HTML
<html>
|
||
<head>
|
||
<title>Mixer app</title>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
|
||
<script src="./thirdparty/jquery/jquery-3.6.0.js?asdf"></script>
|
||
<script src="./thirdparty/jquery/jquery-ui.js"></script>
|
||
<link rel="stylesheet" href="./thirdparty/jquery/jquery-ui.css">
|
||
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
|
||
<link rel="icon" type="image/png" sizes="32x32" href="./media/favicon-32x32.png" />
|
||
<link rel="icon" type="image/png" sizes="16x16" href="./media/favicon-16x16.png" />
|
||
<link rel="icon" href="./media/favicon.ico" />
|
||
<link itemprop="thumbnailUrl" href="./media/vdoNinja_logo_full.png" />
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link href="https://fonts.googleapis.com/css2?family=Sora:wght@200;400;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root{
|
||
--aspect-ratio: 1.7777777777;
|
||
}
|
||
|
||
body{
|
||
padding:0;
|
||
margin:0;
|
||
background-color: #c9c9c9;
|
||
font-family: 'Sora', sans-serif;
|
||
overflow: hidden;
|
||
position: absolute;
|
||
border-radius: 50px;
|
||
background: #2e445c;
|
||
box-shadow: 20px 20px 60px #273a4e, -20px -20px 60px #354e6a;
|
||
scrollbar-color:#666 #201c29;
|
||
}
|
||
iframe {
|
||
border: 0;
|
||
padding: 0;
|
||
display: block;
|
||
|
||
height: 100%;
|
||
width: 1280px;
|
||
|
||
max-height: calc(100vh - 80px);
|
||
max-width: calc(100vw - 290px);
|
||
|
||
background-color: #0002;
|
||
border-radius: 3px;
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
}
|
||
iframe.aspectRatio{
|
||
max-height: min(calc(100vh - 80px), calc((100vw - 290px) / var(--aspect-ratio)));
|
||
max-width: min(calc((100vh - 80px) * var(--aspect-ratio)), calc(100vw - 290px));
|
||
height: 720px;
|
||
width: 1280px;
|
||
}
|
||
|
||
#inviteOptions{
|
||
border: 0;
|
||
padding: 0;
|
||
display: block;
|
||
height: calc(100vh - 80px);
|
||
width: calc(100vw - 290px);
|
||
max-width:100%;
|
||
padding: 20px;
|
||
margin:0;
|
||
border:0;
|
||
display: inline-block;
|
||
background-color: #DDD;
|
||
border-radius: 18px;
|
||
background: #5b748f;
|
||
box-shadow: inset 20px 20px 40px #556c85,
|
||
inset -20px -20px 40px #617c99;
|
||
}
|
||
.ui-widget-header{
|
||
background: rgb(225,225,225); /* Old browsers */
|
||
background: -moz-linear-gradient(-45deg, rgba(255,255,255,1) 0%, rgba(241,241,241,1) 50%, rgba(225,225,225,1) 51%, rgba(246,246,246,1) 100%); /* FF3.6-15 */
|
||
background: -webkit-linear-gradient(-45deg, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* Chrome10-25,Safari5.1-6 */
|
||
background: linear-gradient(135deg, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%);
|
||
}
|
||
|
||
#containerMenu{
|
||
overflow-x: auto;
|
||
overflow-y: hidden;
|
||
position: absolute;
|
||
left: 290px;
|
||
width: calc(100vw - 290px);
|
||
display: flex;
|
||
top: 0;
|
||
height: 80px;
|
||
}
|
||
#iframeContainer{
|
||
position: absolute;
|
||
left: 290px;
|
||
top: 80px;
|
||
height: 100%;
|
||
}
|
||
#viewlink {
|
||
width:400px;
|
||
}
|
||
#container {
|
||
display:block;
|
||
padding:0px;
|
||
background-color: #e5e5e5;
|
||
}
|
||
button[data-state='true']{
|
||
background-color:#CEF !important;
|
||
}
|
||
.disconnected{
|
||
border: 4px dotted red!important;
|
||
padding: 6px 0.25em 0.25em 0.25em!important;
|
||
outline: dashed 2px black!important;
|
||
}
|
||
.thing:hover{
|
||
animation: horizontalShake 2s;
|
||
animation-iteration-count: once;
|
||
}
|
||
#delete:hover{
|
||
animation: none!important;
|
||
}
|
||
@keyframes horizontalShake {
|
||
0% { transform: translate(3px, 0px) rotate(0deg); }
|
||
20% { transform: translate(7px, 0px) rotate(0deg); }
|
||
80% { transform: translate(8px, 0px) rotate(0deg); }
|
||
100% { transform: translate(-1px, 0px) rotate(0deg); }
|
||
}
|
||
.shake {
|
||
animation: shake 0.5s;
|
||
animation-iteration-count: once;
|
||
}
|
||
@keyframes shake {
|
||
0% { transform: translate(1px, 1px) rotate(0deg); }
|
||
10% { transform: translate(-1px, -2px) rotate(-1deg); }
|
||
20% { transform: translate(-3px, 0px) rotate(1deg); }
|
||
30% { transform: translate(3px, 2px) rotate(0deg); }
|
||
40% { transform: translate(1px, -1px) rotate(1deg); }
|
||
50% { transform: translate(-1px, 2px) rotate(-1deg); }
|
||
60% { transform: translate(-3px, 1px) rotate(0deg); }
|
||
70% { transform: translate(3px, 1px) rotate(-1deg); }
|
||
80% { transform: translate(-1px, -1px) rotate(1deg); }
|
||
90% { transform: translate(1px, 2px) rotate(0deg); }
|
||
100% { transform: translate(1px, -2px) rotate(-1deg); }
|
||
}
|
||
input{
|
||
padding:5px;
|
||
margin:5px;
|
||
border-radius: 3px;
|
||
}
|
||
.menuButton{
|
||
width: 92%;
|
||
}
|
||
button{
|
||
padding:5px;
|
||
margin:5px;
|
||
border-radius: 3px;
|
||
cursor:pointer;
|
||
background: linear-gradient(135deg, rgba(238,238,238,1) 60%,rgb(225, 225, 225, 1) 80%,rgb(210, 209, 209, 1) 100%);
|
||
}
|
||
canvas{
|
||
padding:10px;
|
||
cursor:pointer;
|
||
border-radius: 10px;
|
||
box-shadow: 2px 2px 6px #273a4e, -2px -2px 6px #354e6a;
|
||
}
|
||
h2 {
|
||
text-shadow: 0 0 2px #a7a7a7;
|
||
color: #000b3a;
|
||
}
|
||
.inline{
|
||
display:inline-block;
|
||
}
|
||
table {
|
||
font-size: 1em;
|
||
}
|
||
|
||
::-webkit-scrollbar {
|
||
width: 15px;
|
||
}
|
||
|
||
::-webkit-scrollbar-track {
|
||
-webkit-box-shadow: inset 0 0 13px rgb(0 0 0 / 90%);
|
||
border-radius: 4px;
|
||
}
|
||
|
||
::-webkit-scrollbar-thumb {
|
||
border-radius: 4px;
|
||
-webkit-box-shadow: inset 0 0 16px rgb(150 150 150 / 100%);
|
||
border: solid 3px transparent;
|
||
}
|
||
|
||
.ui-draggable, .ui-droppable {
|
||
background-position: top;
|
||
}
|
||
#containerMenu2 {
|
||
width: calc(100vw - 300px);
|
||
position: absolute;
|
||
left: 300px;
|
||
margin: 20px 0;
|
||
}
|
||
|
||
.draggable { width: 150px; height: 150px; padding: 0; margin:0; border:0; }
|
||
.resizable { width: 150px; height: 150px; padding: 0; margin:0; border:0; }
|
||
.resizable h3 { text-align: center; margin: 0; cursor: grab; border: 1px solid black;}
|
||
.ui-menu { width: 150px; }
|
||
|
||
.ui-state-selected {
|
||
background-color: #64b1ff;
|
||
}
|
||
.ui-state-disabled {
|
||
background-color: grey;
|
||
}
|
||
|
||
.widget {
|
||
background-color: #DDD;
|
||
position: absolute;
|
||
}
|
||
#canvas{
|
||
background-color: #000;
|
||
width: 1280px;
|
||
height: 720px;
|
||
margin:0;
|
||
padding:0;
|
||
border:0;
|
||
display: inline-block;
|
||
}
|
||
|
||
#sceneSettings{
|
||
height: calc(100vh - 80px);
|
||
width: calc(100vw - 290px);
|
||
padding: 20px;
|
||
margin:0;
|
||
border:0;
|
||
display: inline-block;
|
||
background-color: #DDD;
|
||
border-radius: 18px;
|
||
background: #5b748f;
|
||
box-shadow: inset 20px 20px 40px #556c85,
|
||
inset -20px -20px 40px #617c99;
|
||
}
|
||
|
||
#sceneSettings > h2{
|
||
margin: 4px;
|
||
}
|
||
|
||
.settings {
|
||
display: block;
|
||
background: #c0e3ff;
|
||
position: absolute;
|
||
top: 100px;
|
||
left: 100px;
|
||
z-Index:20;
|
||
}
|
||
|
||
.hidden {
|
||
display:none!important;
|
||
}
|
||
.fadeout {
|
||
visibility: hidden;
|
||
opacity: 0;
|
||
transition: visibility 0s 0.5s, opacity 0.5s linear;
|
||
}
|
||
.hidden2{
|
||
display:none!important;
|
||
}
|
||
.hidden3{
|
||
display:none!important;
|
||
}
|
||
|
||
.thing {
|
||
width: 100px;
|
||
padding: 10px 0.5em 0.5em 0.5em;
|
||
margin: 6px;
|
||
border: #565656 solid 1px;
|
||
background: rgba(0,0,0,0.8);
|
||
color: white;
|
||
font-family: sans-serif;
|
||
cursor: grab;
|
||
text-align: center;
|
||
border-radius: 6px;
|
||
word-wrap: break-word;
|
||
box-shadow: inset 6px 6px 6px #dadada1c, inset -6px -6px 6px #27272724;
|
||
}
|
||
.empty {
|
||
width: 100px;
|
||
padding: 10px 0.5em 0 0.5em;
|
||
margin: 0.5em 0.4em;
|
||
background: rgba(0,0,0,0.8);
|
||
color: white;
|
||
font-family: sans-serif;
|
||
user-select: none;
|
||
text-align: center;
|
||
border-radius: 6px;
|
||
height: 1.7em;
|
||
cursor: crosshair;
|
||
border: 1px solid black;
|
||
}
|
||
.col {
|
||
width: 130px;
|
||
height: calc(100vh - 20px);
|
||
padding: 5px;
|
||
border: 1px solid;
|
||
border-radius: 5px;
|
||
position: relative;
|
||
float: left;
|
||
user-select: none;
|
||
}
|
||
.pressed>canvas{
|
||
border: solid 2px black;
|
||
background-color: #FFFA;
|
||
}
|
||
button.pressed {
|
||
background-color: #CEF;
|
||
}
|
||
.editButton{
|
||
display:none;
|
||
position:absolute;
|
||
margin: 20px 14px;
|
||
z-index:2;
|
||
}
|
||
.setButton{
|
||
display:none;
|
||
position:absolute;
|
||
margin: 20px 57px;
|
||
z-index:2;
|
||
}
|
||
.canvasContainer{
|
||
display:inline-block;
|
||
}
|
||
.canvasContainer>canvas{
|
||
transform: scale(calc( var(--aspect-ratio) / (16 / 9)), 1);
|
||
}
|
||
.pressed>button{
|
||
display:inline-block;
|
||
}
|
||
b {
|
||
text-shadow: 0 0 1px #f4f4f4;
|
||
}
|
||
a {
|
||
display: inline-block;
|
||
margin: 5px;
|
||
background-color: #c9c9c9;
|
||
border: 2px solid black;
|
||
padding: 4px;
|
||
border-radius: 6px;
|
||
cursor:pointer;
|
||
}
|
||
#delete {
|
||
background-color: rgb(191 191 191);
|
||
text-align: center;
|
||
border: 1px solid black;
|
||
color: black;
|
||
cursor: crosshair;
|
||
margin: 5.5px;
|
||
border-radius: 0px;
|
||
}
|
||
|
||
.modal {
|
||
display: none;
|
||
position: fixed;
|
||
padding-top: 50px;
|
||
left: 0;
|
||
top: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background-color: rgb(0, 0, 0);
|
||
background-color: rgba(0, 0, 0, 0.5);
|
||
z-Index: 20;
|
||
|
||
}
|
||
.modal-content {
|
||
position: relative;
|
||
padding: 20px;
|
||
margin: auto;
|
||
width: 75%;
|
||
-webkit-animation-name: animatetop;
|
||
-webkit-animation-duration: 0.4s;
|
||
animation-name: animatetop;
|
||
animation-duration: 0.4s;
|
||
border-radius: 4px;
|
||
background-color: #e2e2e2;
|
||
background-image: url("data:image/svg+xml,%3Csvg width='6' height='6' viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%239C92AC' fill-opacity='0.1' fill-rule='evenodd'%3E%3Cpath d='M5 0h1L0 6V5zM6 5v1H5z'/%3E%3C/g%3E%3C/svg%3E");
|
||
}
|
||
.close-btn {
|
||
float: right;
|
||
color: lightgray;
|
||
font-size: 24px;
|
||
font-weight: bold;
|
||
}
|
||
.close-btn:hover {
|
||
color: darkgray;
|
||
cursor:pointer;
|
||
}
|
||
@-webkit-keyframes animatetop {
|
||
from {top:-300px; opacity:0}
|
||
to {top:0; opacity:1}
|
||
}
|
||
@keyframes animatetop {
|
||
from {top:-300px; opacity:0}
|
||
to {top:0; opacity:1}
|
||
}
|
||
|
||
#welcomeWindow{
|
||
display:none;
|
||
position:absolute;
|
||
top:0;
|
||
left:0;
|
||
width:100vw;
|
||
height:100vh;
|
||
z-index:5;
|
||
background: #2775dc;
|
||
box-shadow: 20px 20px 60px #51729d,
|
||
-20px -20px 60px #6d9ad5;
|
||
background: -moz-linear-gradient(-45deg, rgba(59,103,158,1) 2%, rgba(43,136,217,1) 50%, rgba(32,124,202,1) 79%, rgba(89, 165, 224,1) 100%); /* FF3.6-15 */
|
||
background: -webkit-linear-gradient(-45deg, rgba(59,103,158,1) 2%,rgba(56, 134, 202,1) 50%,rgba(32,124,202,1) 79%,rgba(89, 165, 224,1) 100%); /* Chrome10-25,Safari5.1-6 */
|
||
background: linear-gradient(135deg, rgba(59,103,158,1) 2%,rgba(56, 134, 202,1) 50%,rgba(32,124,202,1) 79%,rgba(89, 165, 224,1) 100%);
|
||
background: linear-gradient(135deg, rgba(59,103,158,1) 2%,rgba(56, 134, 202,1) 50%,rgba(32,124,202,0.8) 79%,rgba(89, 165, 224,1) 100%), url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500' height='500'%3E%3Cfilter id='noise' x='0' y='0'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3CfeBlend mode='screen'/%3E%3C/filter%3E%3Crect width='500' height='500' filter='url(%23noise)' opacity='0.5'/%3E%3C/svg%3E");
|
||
}
|
||
.center-content{
|
||
align-content: center;
|
||
margin: 20px auto;
|
||
display: block;
|
||
width: 500px;
|
||
max-width: 100%;
|
||
}
|
||
.footer {
|
||
bottom: 0;
|
||
display: inline-block;
|
||
vertical-align: middle;
|
||
margin: 5px 20px;
|
||
height: 28px;
|
||
display: flex;
|
||
align-items: center;
|
||
position: fixed;
|
||
right: 0;
|
||
}
|
||
.footer>div{
|
||
align-items: center;
|
||
}
|
||
|
||
.discord{
|
||
background-image: url("data:image/svg+xml,%3Csvg width='71' height='55' viewBox='0 0 71 55' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg clip-path='url(%23clip0)'%3E%3Cpath d='M60.1045 4.8978C55.5792 2.8214 50.7265 1.2916 45.6527 0.41542C45.5603 0.39851 45.468 0.440769 45.4204 0.525289C44.7963 1.6353 44.105 3.0834 43.6209 4.2216C38.1637 3.4046 32.7345 3.4046 27.3892 4.2216C26.905 3.0581 26.1886 1.6353 25.5617 0.525289C25.5141 0.443589 25.4218 0.40133 25.3294 0.41542C20.2584 1.2888 15.4057 2.8186 10.8776 4.8978C10.8384 4.9147 10.8048 4.9429 10.7825 4.9795C1.57795 18.7309 -0.943561 32.1443 0.293408 45.3914C0.299005 45.4562 0.335386 45.5182 0.385761 45.5576C6.45866 50.0174 12.3413 52.7249 18.1147 54.5195C18.2071 54.5477 18.305 54.5139 18.3638 54.4378C19.7295 52.5728 20.9469 50.6063 21.9907 48.5383C22.0523 48.4172 21.9935 48.2735 21.8676 48.2256C19.9366 47.4931 18.0979 46.6 16.3292 45.5858C16.1893 45.5041 16.1781 45.304 16.3068 45.2082C16.679 44.9293 17.0513 44.6391 17.4067 44.3461C17.471 44.2926 17.5606 44.2813 17.6362 44.3151C29.2558 49.6202 41.8354 49.6202 53.3179 44.3151C53.3935 44.2785 53.4831 44.2898 53.5502 44.3433C53.9057 44.6363 54.2779 44.9293 54.6529 45.2082C54.7816 45.304 54.7732 45.5041 54.6333 45.5858C52.8646 46.6197 51.0259 47.4931 49.0921 48.2228C48.9662 48.2707 48.9102 48.4172 48.9718 48.5383C50.038 50.6034 51.2554 52.5699 52.5959 54.435C52.6519 54.5139 52.7526 54.5477 52.845 54.5195C58.6464 52.7249 64.529 50.0174 70.6019 45.5576C70.6551 45.5182 70.6887 45.459 70.6943 45.3942C72.1747 30.0791 68.2147 16.7757 60.1968 4.9823C60.1772 4.9429 60.1437 4.9147 60.1045 4.8978ZM23.7259 37.3253C20.2276 37.3253 17.3451 34.1136 17.3451 30.1693C17.3451 26.225 20.1717 23.0133 23.7259 23.0133C27.308 23.0133 30.1626 26.2532 30.1066 30.1693C30.1066 34.1136 27.28 37.3253 23.7259 37.3253ZM47.3178 37.3253C43.8196 37.3253 40.9371 34.1136 40.9371 30.1693C40.9371 26.225 43.7636 23.0133 47.3178 23.0133C50.9 23.0133 53.7545 26.2532 53.6986 30.1693C53.6986 34.1136 50.9 37.3253 47.3178 37.3253Z' fill='%23ffffff'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0'%3E%3Crect width='71' height='55' fill='white'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E");
|
||
background-size: contain;
|
||
background-repeat: no-repeat;
|
||
width:14px;
|
||
height:10px;
|
||
border:0;
|
||
background-color:#0000;
|
||
}
|
||
|
||
.github {
|
||
background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z'/%3E%3C/svg%3E");
|
||
background-size: contain;
|
||
width:10px;
|
||
height:10px;
|
||
border:0;
|
||
background-color:#0000;
|
||
}
|
||
#containermenu>div:nth-child(1)>div::before {
|
||
content: "0";
|
||
color: #a4a4a4;
|
||
}
|
||
#containermenu>div:nth-child(2)>div::before {
|
||
content: "1";
|
||
color: #a4a4a4;
|
||
}
|
||
#containermenu>div:nth-child(3)>div::before {
|
||
content: "2";
|
||
color: #a4a4a4;
|
||
}
|
||
#containermenu>div:nth-child(4)>div::before {
|
||
content: "3";
|
||
color: #a4a4a4;
|
||
}
|
||
#containermenu>div:nth-child(5)>div::before {
|
||
content: "4";
|
||
color: #a4a4a4;
|
||
}
|
||
#containermenu>div:nth-child(6)>div::before {
|
||
content: "5";
|
||
color: #a4a4a4;
|
||
}
|
||
#containermenu>div:nth-child(7)>div::before {
|
||
content: "6";
|
||
color: #a4a4a4;
|
||
}
|
||
#containermenu>div:nth-child(8)>div::before {
|
||
content: "7";
|
||
color: #a4a4a4;
|
||
}
|
||
#containermenu>div:nth-child(9)>div::before {
|
||
content: "8";
|
||
color: #a4a4a4;
|
||
}
|
||
#containermenu>div:nth-child(9)>div::before {
|
||
content: "9";
|
||
color: #a4a4a4;
|
||
}
|
||
#containermenu>div>div {
|
||
width: 15px;
|
||
height: 15px;
|
||
border-radius: 10px;
|
||
margin: 0 auto;
|
||
color: #a4a4a4;
|
||
position: relative;
|
||
left: 4px;
|
||
font-size: 70%;
|
||
cursor:help;
|
||
}
|
||
.tooltip {
|
||
z-index: 100;
|
||
}
|
||
.tooltip .tooltiptext {
|
||
visibility: hidden;
|
||
background-color: #333;
|
||
color: #fff;
|
||
text-align: center;
|
||
border-radius: 3px;
|
||
padding: 3px;
|
||
overflow: auto;
|
||
margin: 0; position:relative;
|
||
font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus,Code2000, Code2001, Code2002, Musica, serif, LastResort;
|
||
|
||
}
|
||
.tooltip:hover .tooltiptext {
|
||
visibility: visible;
|
||
}
|
||
.randomRoomName{
|
||
|
||
width: 24px;
|
||
height: 24px;
|
||
background-size: contain;
|
||
background-repeat: no-repeat;
|
||
border-radius: 5px;
|
||
background: rgb(238,238,238);
|
||
background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 29 29'%3E%3Cpath d='M18 9v-3c-1 0-3.308-.188-4.506 2.216l-4.218 8.461c-1.015 2.036-3.094 3.323-5.37 3.323h-3.906v-2h3.906c1.517 0 2.903-.858 3.58-2.216l4.218-8.461c1.356-2.721 3.674-3.323 6.296-3.323v-3l6 4-6 4zm-9.463 1.324l1.117-2.242c-1.235-2.479-2.899-4.082-5.748-4.082h-3.906v2h3.906c2.872 0 3.644 2.343 4.631 4.324zm15.463 8.676l-6-4v3c-3.78 0-4.019-1.238-5.556-4.322l-1.118 2.241c1.021 2.049 2.1 4.081 6.674 4.081v3l6-4z'/%3E%3C/svg%3E"), linear-gradient(135deg, rgba(238,238,238,1) 0%,rgba(204,204,204,1) 100%);
|
||
}
|
||
#demoDrop{
|
||
background-color: #30892c;
|
||
cursor: help;
|
||
}
|
||
.demoThing{
|
||
width: 100px;
|
||
padding: 10px 0.5em 0.5em 0.5em;
|
||
margin: 6px;
|
||
border: #565656 solid 1px;
|
||
background: rgba(0,0,0,0.8);
|
||
color: white;
|
||
font-family: sans-serif;
|
||
cursor: grab;
|
||
text-align: center;
|
||
border-radius: 6px;
|
||
word-wrap: break-word;
|
||
box-shadow: inset 6px 6px 6px #dadada1c, inset -6px -6px 6px #27272724;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="col" id="sources">
|
||
<div id="col2" ondrop="dropRemove(event)" ondragover="allowDrop(event)" ondragenter="dragenter(event)" ondragleave="dragleave(event)">
|
||
<div class="demoThing" draggable="false" id="demoDrop" title="Drag stream IDs as guest join to a corresponding SLOT, then active the desired layout.">Streams IDs appearing above are draggable</div>
|
||
<div class="thing" draggable="false" id="delete" title="Dragging stream IDs here will either remove them from a SLOT or delete them all together.">Remove</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col" id="col1" ondrop="drop(event)" ondragover="allowDrop(event)" ondragenter="dragenter(event)" title="Drag a stream ID here, to the desired slot, then activate the desired layout" ondragleave="dragleave(event)">
|
||
<div class="empty" data-slot="1" >SLOT 1</div>
|
||
<div class="empty" data-slot="2">SLOT 2</div>
|
||
<div class="empty" data-slot="3">SLOT 3</div>
|
||
<div class="empty" data-slot="4">SLOT 4</div>
|
||
</div>
|
||
<div id="container">
|
||
<div id="containermenu"></div>
|
||
<div id="containermenu2" class="hidden">
|
||
<button onclick="addElement();">➕ Add Item</button>
|
||
<button onclick="saveScene(false);">💾 Save Scene</button>
|
||
<button onclick="saveScene(true);">🆕 Save As New Scene</button>
|
||
<button onclick="copyJSON();" title="This can be used with &format directly in VDO.Ninja without the mixer app.">Show as JSON</button>
|
||
<button onclick="removeScene();">🗑️ Remove Scene</button>
|
||
<button onclick="saveScene(false);closeScene();">💾❌ Save and Close</button>
|
||
<button onclick="closeScene();">❌ Close Scene Maker</button>
|
||
</div>
|
||
</div>
|
||
<div id="welcomeWindow">
|
||
<div class="center-content">
|
||
<div class="title"><h1 class="main-heading">Mixer App</h1><h2>Video chat with custom <b>layouts</b></h2></div>
|
||
|
||
<label for="roomname"><input name="roomname" id="roomname" type="text" placeholder="Room Name" />
|
||
<font class="tooltip">
|
||
<button onclick="randomRoomName();" class="randomRoomName"></button><span class="tooltiptext">Generate a random room name</span>
|
||
</font>
|
||
<br />
|
||
<label for="roompassword"><input name="roompassword" id="roompassword" type="text" placeholder="Room Password (optional)"/><br />
|
||
<button onclick="startRoom();">Get started!</button><br /><br />
|
||
<div class="footer">
|
||
<div>
|
||
<a href="https://discord.vdo.ninja" class="discord" target="_blank"></a>
|
||
</div>
|
||
<div>
|
||
<a class="github" href="https://github.com/steveseguin/vdoninja" rel="noopener" target="_blank" title="Star steveseguin/vdoninja on GitHub"></a>
|
||
</div>
|
||
<div style="cursor:pointer;" onclick="window.open('https://vdo.ninja');">Powered by VDO.Ninja</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="iframeContainer">
|
||
<div id='canvas' class="hidden">
|
||
</div>
|
||
<div id='sceneSettings' class="hidden2">
|
||
<h2>General Settings</h2>
|
||
<h4>Aspect Ratio</h4>
|
||
<input type="checkbox" class="aspectbutton" onchange="changeAspectRatio(16/9.0, this);">16:9
|
||
<input type="checkbox" class="aspectbutton" onchange="changeAspectRatio(9.0/16, this);">9:16
|
||
<input type="checkbox" class="aspectbutton" onchange="changeAspectRatio(1.0, this);">1:1
|
||
<br /><small><i>This just impacts the aspect ratio of the local preview.</i></small><br />
|
||
|
||
<h4>Remove all Layouts</h4>
|
||
<button onclick="wipeLayouts();">This will remove all the scene layouts from the current session.</button><br />
|
||
|
||
<h4>Export settings</h4>
|
||
<button onclick="exportSession();">Export all scenes and settings to disk</button><br />
|
||
<h4>Import settings</h4>
|
||
Import scenes and settings from local file:<br /><input type="file" accept=".json" onchange="importSession(event);"/><br /><br />
|
||
<button onclick="modal.style.display = 'none';">Close Settings</button>
|
||
</div>
|
||
<div id='roomSettings' class="hidden2">
|
||
<h2>Room Setup</h2>
|
||
|
||
<br /><br />
|
||
<button onclick="showSettings();">Close</button>
|
||
</div>
|
||
<div id='inviteOptions' class="hidden">
|
||
<h2>Invite options</h2>
|
||
<h4>Your room name is: <b class="roomname">ROOMNAME</b></h4>
|
||
<h4>Create new invite</h4>
|
||
<a class="inviteLink">Invite Link</a>
|
||
<br /><br />
|
||
<button onclick="modal.style.display = 'none';">Close</button>
|
||
</div>
|
||
</div>
|
||
<div id="modal" class="modal">
|
||
<div class="modal-content">
|
||
<span class="close-btn">×</span>
|
||
<div id="modal-content">
|
||
<p>this is the text inside the modal</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
|
||
function allowDrop(ev) {
|
||
ev.preventDefault();
|
||
}
|
||
|
||
(function(w) {
|
||
w.URLSearchParams = w.URLSearchParams || function(searchString) {
|
||
var self = this;
|
||
searchString = searchString.replace("??", "?");
|
||
self.searchString = searchString;
|
||
self.get = function(name) {
|
||
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(self.searchString);
|
||
if (results == null) {
|
||
return null;
|
||
} else {
|
||
return decodeURI(results[1]) || 0;
|
||
}
|
||
};
|
||
};
|
||
|
||
})(window);
|
||
|
||
function warnlog(msg){
|
||
console.warn(msg);
|
||
}
|
||
function errorlog(msg){
|
||
console.error(msg);
|
||
}
|
||
function log(msg){
|
||
console.log(msg);
|
||
}
|
||
|
||
function sanitizeRoomName(roomid) {
|
||
if (!roomid){
|
||
return false;
|
||
}
|
||
roomid = roomid.trim();
|
||
if (roomid === "") {
|
||
return false;
|
||
} else if (!roomid) {
|
||
return false;
|
||
} else if (roomid=="test") {
|
||
return false;
|
||
}
|
||
var roomid = roomid.replace(/[\W]+/g, "_");
|
||
if (roomid.length > 50) {
|
||
roomid = roomid.substring(0, 50);
|
||
}
|
||
return roomid;
|
||
}
|
||
|
||
var urlEdited = window.location.search.replace(/\?\?/g, "?");
|
||
urlEdited = urlEdited.replace(/\?/g, "&");
|
||
urlEdited = urlEdited.replace(/\&/, "?");
|
||
|
||
if (urlEdited !== window.location.search){
|
||
warnlog(window.location.search + " changed to " + urlEdited);
|
||
window.history.pushState({path: urlEdited.toString()}, '', urlEdited.toString());
|
||
}
|
||
var urlParams = new URLSearchParams(urlEdited);
|
||
|
||
var password = false;
|
||
if (urlParams.has("password")){
|
||
password = urlParams.get("password");
|
||
}
|
||
|
||
var aspectRatio = 16/9.0;
|
||
document.documentElement.style.setProperty('--aspect-ratio', aspectRatio);
|
||
|
||
var roomname = false;
|
||
if (urlParams.has("room") || urlParams.has("dir") || urlParams.has("director")){
|
||
roomname = urlParams.get("room") || urlParams.get("dir") || urlParams.get("director");
|
||
roomname = sanitizeRoomName(roomname);
|
||
}
|
||
|
||
function randomRoomName(){
|
||
var rndroom = generateString(8);
|
||
document.getElementById("roomname").value = rndroom;
|
||
}
|
||
|
||
function startRoom(){
|
||
var pid = document.getElementById("roompassword").value.trim();
|
||
if (pid){
|
||
password = pid;
|
||
}
|
||
|
||
var rid = document.getElementById("roomname").value.trim();
|
||
if (rid == "test"){
|
||
alert("Please enter a unique room name");
|
||
}
|
||
rid = sanitizeRoomName(rid);
|
||
if (rid){
|
||
if (this){
|
||
this.disabled = true;
|
||
this.onclick = null;
|
||
}
|
||
roomname = rid;
|
||
loadIframe();
|
||
document.getElementById("welcomeWindow").classList.add("fadeout");
|
||
setTimeout(function(){
|
||
document.getElementById("welcomeWindow").classList.add("hidden");
|
||
},500);
|
||
} else {
|
||
document.getElementById("roomname").classList.remove("shake");
|
||
setTimeout(function(){document.getElementById("roomname").classList.add("shake");},10);
|
||
}
|
||
}
|
||
|
||
function errorlog(e,a=null,b=null){
|
||
console.error(e);
|
||
}
|
||
|
||
var currentLayout = {};
|
||
|
||
$(function(){
|
||
$( "#containermenu" ).sortable({
|
||
stop: function( event, ui ) {saveSession();},
|
||
distance: 20
|
||
});
|
||
});
|
||
|
||
function swapNodes(n1, n2) {
|
||
var p1 = n1.parentNode;
|
||
var p2 = n2.parentNode;
|
||
var i1, i2;
|
||
|
||
if ( !p1 || !p2 || p1.isEqualNode(n2) || p2.isEqualNode(n1) ) return;
|
||
|
||
for (var i = 0; i < p1.children.length; i++) {
|
||
if (p1.children[i].isEqualNode(n1)) {
|
||
i1 = i;
|
||
}
|
||
}
|
||
for (var i = 0; i < p2.children.length; i++) {
|
||
if (p2.children[i].isEqualNode(n2)) {
|
||
i2 = i;
|
||
}
|
||
}
|
||
|
||
if ( p1.isEqualNode(p2) && i1 < i2 ) {
|
||
i2++;
|
||
}
|
||
p1.insertBefore(n2, p1.children[i1]);
|
||
p2.insertBefore(n1, p2.children[i2]);
|
||
}
|
||
|
||
function drag(ev) {
|
||
var data = ev.dataTransfer.getData("text");
|
||
var origThing = document.getElementById(data);
|
||
|
||
ev.dataTransfer.setData("text", ev.target.id);
|
||
var eles = document.querySelectorAll(".thing");
|
||
for (var i=0;i<eles.length;i++){
|
||
if (eles[i].id == ev.target.id){continue;}
|
||
if (!ev.target.dataset.slot){
|
||
if (eles[i].id == "delete"){
|
||
if (!ev.target.classList.contains("disconnected")){
|
||
continue;
|
||
} else {
|
||
eles[i].style.boxShadow = "0px 0px 8px 2px #F00";
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
|
||
eles[i].style.boxShadow = "0px 0px 8px 2px #Fff";
|
||
}
|
||
var eles = document.querySelectorAll(".empty");
|
||
for (var i=0;i<eles.length;i++){
|
||
eles[i].style.boxShadow = "0px 0px 8px 2px #Fff";
|
||
}
|
||
}
|
||
|
||
function drop(ev) {
|
||
ev.preventDefault();
|
||
var data = ev.dataTransfer.getData("text");
|
||
var origThing = document.getElementById(data);
|
||
console.log(origThing);
|
||
console.log(data);
|
||
console.log(ev);
|
||
ev.target.style.border = "";
|
||
origThing.style.border = "";
|
||
|
||
if (ev.target.classList.contains("thing")){
|
||
|
||
swapNodes( ev.target, origThing);
|
||
var slot = parseInt(origThing.dataset.slot);
|
||
origThing.dataset.slot = parseInt(ev.target.dataset.slot);
|
||
ev.target.dataset.slot = slot;
|
||
var oldColor = origThing.style.backgroundColor;
|
||
origThing.style.backgroundColor = ev.target.style.backgroundColor;
|
||
ev.target.style.backgroundColor = oldColor;
|
||
//ev.target.classList.add("empty");
|
||
} else if (ev.target.classList.contains("empty")){
|
||
|
||
if (!ev.target.dataset.slot){return;}
|
||
if (ev.target.dataset.slot=="undefined"){return;}
|
||
if (ev.target.dataset.slot=="undefined"){return;}
|
||
|
||
ev.target.parentNode.insertBefore(origThing, ev.target.nextSibling);
|
||
|
||
console.warn(origThing);
|
||
|
||
if (origThing.dataset.slot && (origThing.dataset.slot!=="undefined")){
|
||
document.querySelectorAll("[data-slot='"+origThing.dataset.slot+"']").forEach(ele=>{ele.style.display = "block";})
|
||
document.querySelectorAll("[data-slot='"+origThing.dataset.slot+"']").forEach(ele=>{ele.classList.remove("hidden");})
|
||
}
|
||
origThing.dataset.slot = ev.target.dataset.slot;
|
||
ev.target.style.display = "none";
|
||
ev.target.classList.add("hidden");
|
||
//ev.target.classList.remove("empty");
|
||
origThing.style.backgroundColor = ev.target.style.backgroundColor;
|
||
}
|
||
|
||
var eles = document.querySelectorAll(".thing");
|
||
for (var i=0;i<eles.length;i++){
|
||
eles[i].style.boxShadow = "unset";
|
||
}
|
||
var eles = document.querySelectorAll(".empty");
|
||
for (var i=0;i<eles.length;i++){
|
||
eles[i].style.boxShadow = "unset";
|
||
}
|
||
}
|
||
|
||
function dragenter(event) {
|
||
event.preventDefault();
|
||
if ( event.target.classList.contains("thing") ) {
|
||
event.target.style.border = "3px dotted black";
|
||
} else if (event.target.classList.contains("empty")){
|
||
event.target.style.border = "3px dotted black";
|
||
}
|
||
}
|
||
|
||
function dragleave(event) {
|
||
event.preventDefault();
|
||
if (event.target.classList.contains("thing")){
|
||
event.target.style.border = "";
|
||
} else if (event.target.classList.contains("empty")){
|
||
event.target.style.border = "";
|
||
}
|
||
}
|
||
|
||
|
||
function dropRemove(ev) {
|
||
ev.preventDefault();
|
||
var data = ev.dataTransfer.getData("text");
|
||
var origThing = document.getElementById(data);
|
||
|
||
ev.target.style.border = "";
|
||
origThing.style.border = "";
|
||
|
||
if (origThing.dataset.slot){
|
||
document.querySelector("[data-slot='"+origThing.dataset.slot+"']").style.display = "block";
|
||
document.querySelector("[data-slot='"+origThing.dataset.slot+"']").classList.remove("hidden");
|
||
document.querySelector("[data-slot='"+origThing.dataset.slot+"']").classList.add("empty");
|
||
delete origThing.dataset.slot;
|
||
}
|
||
|
||
origThing.style.backgroundColor = "#000";
|
||
if (ev.target.classList.contains("thing")){
|
||
ev.target.parentNode.insertBefore(origThing, ev.target.nextSibling);
|
||
} else {
|
||
ev.target.appendChild(origThing);
|
||
}
|
||
document.getElementById("col2").appendChild(document.getElementById("delete"));
|
||
|
||
var eles = document.querySelectorAll(".thing");
|
||
for (var i=0;i<eles.length;i++){
|
||
eles[i].style.boxShadow = "unset";
|
||
}
|
||
var eles = document.querySelectorAll(".empty");
|
||
for (var i=0;i<eles.length;i++){
|
||
eles[i].style.boxShadow = "unset";
|
||
}
|
||
|
||
if (ev.target.id == "delete"){
|
||
if (origThing.classList.contains("disconnected")){
|
||
if (!origThing.dataset.slot){
|
||
origThing.remove();
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
var streamIDs = [];
|
||
var slotsNeeded = 1;
|
||
var lastLayout = false;
|
||
|
||
function updateList(){
|
||
//<div id="col2" ondrop="dropRemove(event)" ondragover="allowDrop(event)">
|
||
// <div class="thing" draggable="true" ondragstart="drag(event)" id="thing4">THING 4</div>
|
||
// <div class="thing" draggable="true" ondragstart="drag(event)" id="thing1">THING 1</div>
|
||
//</div>
|
||
for (var i=0;i<streamIDs.length;i++){
|
||
if (!document.getElementById("sid_"+streamIDs[i])){
|
||
var thing = document.createElement("div");
|
||
thing.draggable = true;
|
||
thing.classList.add("thing");
|
||
thing.ondblclick = function(ev){
|
||
var origThing = ev.target;
|
||
console.log(ev);
|
||
if (origThing.parentNode.id == "col1"){return;}
|
||
ev.preventDefault();
|
||
var target = document.querySelector("[data-slot][class='empty']:not([class='hidden'])");
|
||
console.log(origThing);
|
||
console.log(target);
|
||
origThing.style.border = "";
|
||
|
||
var eles = document.querySelectorAll(".thing");
|
||
for (var i=0;i<eles.length;i++){
|
||
eles[i].style.boxShadow = "unset";
|
||
}
|
||
var eles = document.querySelectorAll(".empty");
|
||
for (var i=0;i<eles.length;i++){
|
||
eles[i].style.boxShadow = "unset";
|
||
}
|
||
|
||
if (target.classList.contains("thing")){
|
||
swapNodes( target, origThing);
|
||
var slot = origThing.dataset.slot;
|
||
origThing.dataset.slot = target.dataset.slot;
|
||
target.dataset.slot = slot;
|
||
var oldColor = origThing.style.backgroundColor;
|
||
origThing.style.backgroundColor = target.style.backgroundColor;
|
||
target.style.backgroundColor = oldColor;
|
||
//target.classList.add("empty");
|
||
//target.classList.add("empty");
|
||
} else if (target.classList.contains("empty")){
|
||
|
||
if (!target.dataset.slot){return;}
|
||
if (target.dataset.slot=="undefined"){return;}
|
||
if (target.dataset.slot=="undefined"){return;}
|
||
target.parentNode.insertBefore(origThing, target.nextSibling);
|
||
|
||
console.warn(origThing);
|
||
|
||
if (origThing.dataset.slot && (origThing.dataset.slot!=="undefined")){
|
||
document.querySelector("[data-slot='"+origThing.dataset.slot+"']").style.display = "block";
|
||
document.querySelector("[data-slot='"+origThing.dataset.slot+"']").classList.remove("hidden");
|
||
}
|
||
origThing.dataset.slot = target.dataset.slot;
|
||
target.style.display = "none";
|
||
target.classList.add("hidden");
|
||
//target.classList.remove("empty");
|
||
origThing.style.backgroundColor = target.style.backgroundColor;
|
||
}
|
||
};
|
||
thing.addEventListener("dragstart", drag);
|
||
|
||
thing.dataset.sid = streamIDs[i];
|
||
thing.id = "sid_"+streamIDs[i];
|
||
thing.innerText = streamIDs[i];
|
||
thing.title = "This object represents a media stream. Drag it to a slot to include it in a layout. It will not activate until the layout is re-set or triggered."
|
||
document.getElementById("col2").appendChild(thing);
|
||
|
||
thing.classList.add("shake");
|
||
setTimeout(function(ele){ele.classList.remove("shake");},500,thing);
|
||
} else{
|
||
document.getElementById("sid_"+streamIDs[i]).classList.remove("disconnected");
|
||
document.getElementById("sid_"+streamIDs[i]).title = "Connected and ready to be placed";
|
||
}
|
||
}
|
||
try {
|
||
if (streamIDs.length>2){
|
||
document.getElementById("demoDrop").style.display = "none"
|
||
} else if (streamIDs.length==0){
|
||
document.getElementById("demoDrop").style.display = "unset"
|
||
document.getElementById("col2").appendChild(document.getElementById("demoDrop"));
|
||
} else {
|
||
document.getElementById("col2").appendChild(document.getElementById("demoDrop"));
|
||
}
|
||
}catch(e){}
|
||
document.getElementById("col2").appendChild(document.getElementById("delete"));
|
||
|
||
|
||
}
|
||
|
||
var colors = [
|
||
"#00AAAA",
|
||
"#FF0000",
|
||
"#0000FF",
|
||
"#AA00AA",
|
||
"#00FF00",
|
||
"#AAAA00",
|
||
"#AACC44",
|
||
"#CCAA44",
|
||
"#CC44AA",
|
||
"#44AACC"
|
||
];
|
||
|
||
var savedSession = getStorage("savedSession");
|
||
if (savedSession){
|
||
savedSession = JSON.parse(savedSession);
|
||
} else {
|
||
savedSession = {};
|
||
savedSession.layouts = [];
|
||
|
||
var data = [
|
||
{x:0, y:0, w:100, h:100}
|
||
];
|
||
savedSession.layouts.push(data);
|
||
|
||
|
||
var data = [
|
||
null,
|
||
{x:0, y:0, w:100, h:100}
|
||
];
|
||
savedSession.layouts.push(data);
|
||
|
||
|
||
var data = [
|
||
{x:0, y:25, w:50, h:50, c:false},
|
||
{x:50, y:25, w:50, h:50, c:false}
|
||
];
|
||
savedSession.layouts.push(data);
|
||
|
||
|
||
|
||
var data = [
|
||
{x:70, y:70, w:30, h:30, z:1, c:true},
|
||
{x:0, y:0, w:100, h:100,z:0, c:false}
|
||
];
|
||
savedSession.layouts.push(data);
|
||
|
||
|
||
var data = [
|
||
{x:0, y:0, w:100, h:100,z:0, c:true},
|
||
{x:70, y:70, w:30, h:30, z:1, c:false}
|
||
];
|
||
savedSession.layouts.push(data);
|
||
|
||
|
||
var data = [
|
||
{x:0, y:0, w:20, h:20, z:1, c:true},
|
||
{x:0, y:0, w:100, h:100,z:0, c:false}
|
||
];
|
||
savedSession.layouts.push(data);
|
||
|
||
|
||
var data = [
|
||
{x:0, y:0, w:50, h:50},
|
||
{x:50, y:0, w:50, h:50},
|
||
{x:0, y:50, w:50, h:50},
|
||
{x:50, y:50, w:50, h:50}
|
||
];
|
||
savedSession.layouts.push(data);
|
||
|
||
|
||
var data = [
|
||
{x:0, y:16.667, w:66.667, h:66.667},
|
||
{x:66.667, y:0, w:33.333, h:33.333},
|
||
{x:66.667, y:33.333, w:33.333, h:33.333},
|
||
{x:66.667, y:66.667, w:33.333, h:33.333}
|
||
];
|
||
savedSession.layouts.push(data);
|
||
|
||
|
||
var data = [
|
||
{x:66.667, y:0, w:33.333, h:33.333},
|
||
{x:0, y:16.667, w:66.667, h:66.667},
|
||
{x:66.667, y:33.333, w:33.333, h:33.333},
|
||
{x:66.667, y:66.667, w:33.333, h:33.333}
|
||
];
|
||
savedSession.layouts.push(data);
|
||
|
||
|
||
var data = [
|
||
null,
|
||
null,
|
||
{x:0, y:0, w:100, h:100}
|
||
];
|
||
savedSession.layouts.push(data);
|
||
|
||
|
||
var data = [
|
||
null,
|
||
null,
|
||
null,
|
||
{x:0, y:0, w:100, h:100}
|
||
];
|
||
savedSession.layouts.push(data);
|
||
|
||
|
||
var data = [
|
||
null,
|
||
null,
|
||
{x:70, y:70, w:30, h:30, z:1, c:true},
|
||
{x:0, y:0, w:100, h:100,z:0, c:false}
|
||
];
|
||
savedSession.layouts.push(data);
|
||
|
||
|
||
var data = [
|
||
null,
|
||
null,
|
||
{x:0, y:25, w:50, h:50, c:true},
|
||
{x:50, y:25, w:50, h:50, c:true}
|
||
];
|
||
savedSession.layouts.push(data);
|
||
}
|
||
|
||
function exportSession() {
|
||
var content = JSON.stringify(savedSession);
|
||
var fileName = roomname + ".json";
|
||
var a = document.createElement("a");
|
||
var file = new Blob([content], {type: 'text/plain'});
|
||
a.href = URL.createObjectURL(file);
|
||
a.download = fileName;
|
||
a.click();
|
||
}
|
||
|
||
function importSession(event){
|
||
|
||
var reader = new FileReader();
|
||
reader.onload = function(event){
|
||
console.log(event.target.result);
|
||
try {
|
||
var obj = JSON.parse(event.target.result);
|
||
} catch(e){
|
||
alert("File is not a valid JSON file");
|
||
return;
|
||
}
|
||
if ("layouts" in obj){
|
||
var yes = confirm("Are you sure? This will clear the current session");
|
||
if (!yes){return;}
|
||
savedSession = obj;
|
||
document.getElementById("containermenu").innerHTML = "";
|
||
drawAddNewLayout2();
|
||
drawAddNewLayout3();
|
||
for (var i in savedSession.layouts){
|
||
drawLayout(savedSession.layouts[i]);
|
||
}
|
||
alert("The saved session has been imported and loaded.");
|
||
} else {
|
||
alert("File contains no valid session information");
|
||
}
|
||
};
|
||
reader.readAsText(event.target.files[0]);
|
||
|
||
}
|
||
|
||
function wipeLayouts(){
|
||
|
||
var yes = confirm("Are you sure? This will delete all the layouts.");
|
||
if (!yes){return;}
|
||
|
||
document.getElementById("containermenu").innerHTML = "";
|
||
|
||
drawAddNewLayout2();
|
||
drawAddNewLayout3();
|
||
|
||
savedSession.layouts = [];
|
||
for (var i in savedSession.layouts){
|
||
drawLayout(savedSession.layouts[i]);
|
||
}
|
||
}
|
||
|
||
var injectCSS = `
|
||
.directorsgrid .vidcon {
|
||
display: inline-block !important;
|
||
width: 293.7px !important;
|
||
background: #3e3e3e00;
|
||
color: #FCFCFC;
|
||
vertical-align: top;
|
||
border: 1px solid #2e445c;
|
||
padding: 10px;
|
||
border-radius: 10px;
|
||
background: #2e445c;
|
||
box-shadow: 20px 20px 60px #182430, -20px -20px 60px #283c52;
|
||
}
|
||
`;
|
||
|
||
injectCSS = encodeURIComponent(btoa(injectCSS));
|
||
|
||
function generateString(LLL = 7){
|
||
var text = "";
|
||
var words = ["the","of","to","and","a","in","is","it","you","that","he","was","for","on","are","with","as","I","his","they","be","at","one","have","this","from","or","had","by","word","but","what","some","we","can","out","other","were","all","there","when","up","use","your","how","said","an","each","she","which","do","their","time","if","will","way","about","many","then","them","write","would","like","so","these","her","long","make","thing","see","him","two","has","look","more","day","could","go","come","did","number","sound","no","most","people","my","over","know","water","than","call","first","who","may","down","side","been","now","find","any","new","work","part","take","get","place","made","live","where","after","back","little","only","round","man","year","came","show","every","good","me","give","our","under","name","very","through","just","form","sentence","great","think","say","help","low","line","differ","turn","cause","much","mean","before","move","right","boy","old","too","same","tell","does","set","three","want","air","well","also","play","small","end","put","home","read","hand","port","large","spell","add","even","land","here","must","big","high","such","follow","act","why","ask","men","change","went","light","kind","off","need","house","picture","try","us","again","animal","point","mother","world","near","build","self","earth","father","head","stand","own","page","should","country","found","answer","school","grow","study","still","learn","plant","cover","food","sun","four","between","state","keep","eye","never","last","let","thought","city","tree","cross","farm","hard","start","might","story","saw","far","sea","draw","left","late","run","don't","while","press","close","night","real","life","few","north","open","seem","together","next","white","children","begin","got","walk","example","ease","paper","group","always","music","those","both","mark","often","letter","until","mile","river","car","feet","care","second","book","carry","took","science","eat","room","friend","began","idea","fish","mountain","stop","once","base","hear","horse","cut","sure","watch","color","face","wood","main","enough","plain","girl","usual","young","ready","above","ever","red","list","though","feel","talk","bird","soon","body","dog","family","direct","pose","leave","song","measure","door","product","black","short","numeral","class","wind","question","happen","complete","ship","area","half","rock","order","fire","south","problem","piece","told","knew","pass","since","top","whole","king","space","heard","best","hour","better","true .","during","hundred","five","remember","step","early","hold","west","ground","interest","reach","fast","verb","sing","listen","six","table","travel","less","morning","ten","simple","several","vowel","toward","war","lay","against","pattern","slow","center","love","person","money","serve","appear","road","map","rain","rule","govern","pull","cold","notice","voice","unit","power","town","fine","certain","fly","fall","lead","cry","dark","machine","note","wait","plan","figure","star","box","noun","field","rest","correct","able","pound","done","beauty","drive","stood","contain","front","teach","week","final","gave","green","oh","quick","develop","ocean","warm","free","minute","strong","special","mind","behind","clear","tail","produce","fact","street","inch","multiply","nothing","course","stay","wheel","full","force","blue","object","decide","surface","deep","moon","island","foot","system","busy","test","record","boat","common","gold","possible","plane","stead","dry","wonder","laugh","thousand","ago","ran","check","game","shape","equate","hot","miss","brought","heat","snow","tire","bring","yes","distant","fill","east","paint","language","among","grand","ball","yet","wave","drop","heart","am","present","heavy","dance","engine","position","arm","wide","sail","material","size","vary","settle","speak","weight","general","ice","matter","circle","pair","include","divide","syllable","felt","perhaps","pick","sudden","count","square","reason","length","represent","art","subject","region","energy","hunt","probable","bed","brother","egg","ride","cell","believe","fraction","forest","sit","race","window","store","summer","train","sleep","prove","lone","leg","exercise","wall","catch","mount","wish","sky","board","joy","winter","sat","written","wild","instrument","kept","glass","grass","cow","job","edge","sign","visit","past","soft","fun","bright","gas","weather","month","million","bear","finish","happy","hope","flower","clothe","strange","gone","jump","baby","eight","village","meet","root","buy","raise","solve","metal","whether","push","seven","paragraph","third","shall","held","hair","describe","cook","floor","either","result","burn","hill","safe","cat","century","consider","type","law","bit","coast","copy","phrase","silent","tall","sand","soil","roll","temperature","finger","industry","value","fight","lie","beat","excite","natural","view","sense","ear","else","quite","broke","case","middle","kill","son","lake","moment","scale","loud","spring","observe","child","straight","consonant","nation","dictionary","milk","speed","method","organ","pay","age","section","dress","cloud","surprise","quiet","stone","tiny","climb","cool","design","poor","lot","experiment","bottom","key","iron","single","stick","flat","twenty","skin","smile","crease","hole","trade","melody","trip","office","receive","row","mouth","exact","symbol","die","least","trouble","shout","except","wrote","seed","tone","join","suggest","clean","break","lady","yard","rise","bad","blow","oil","blood","touch","grew","cent","mix","team","wire","cost","lost","brown","wear","garden","equal","sent","choose","fell","fit","flow","fair","bank","collect","save","control","decimal","gentle","woman","captain","practice","separate","difficult","doctor","please","protect","noon","whose","locate","ring","character","insect","caught","period","indicate","radio","spoke","atom","human","history","effect","electric","expect","crop","modern","element","hit","student","corner","party","supply","bone","rail","imagine","provide","agree","thus","capital","won't","chair","danger","fruit","rich","thick","soldier","process","operate","guess","necessary","sharp","wing","create","neighbor","wash","bat","rather","crowd","corn","compare","poem","string","bell","depend","meat","rub","tube","famous","dollar","stream","fear","sight","thin","triangle","planet","hurry","chief","colony","clock","mine","tie","enter","major","fresh","search","send","yellow","gun","allow","print","dead","spot","desert","suit","current","lift","rose","continue","block","chart","hat","sell","success","company","subtract","event","particular","deal","swim","term","opposite","wife","shoe","shoulder","spread","arrange","camp","invent","cotton","born","determine","quart","nine","truck","noise","level","chance","gather","shop","stretch","throw","shine","property","column","molecule","select","wrong","gray","repeat","require","broad","prepare","salt","nose","plural","anger","claim","continent","oxygen","sugar","death","pretty","skill","women","season","solution","magnet","silver","thank","branch","match","suffix","especially","fig","afraid","huge","sister","steel","discuss","forward","similar","guide","experience","score","apple","bought","led","pitch","coat","mass","card","band","rope","slip","win","dream","evening","condition","feed","tool","total","basic","smell","valley","nor","double","seat","arrive","master","track","parent","shore","division","sheet","substance","favor","connect","post","spend","chord","fat","glad","original","share","station","dad","bread","charge","proper","bar","offer","segment","slave","duck","instant","market","degree","populate","chick","dear","enemy","reply","drink","occur","support","speech","nature","range","steam","motion","path","liquid","log","meant","quotient","teeth","shell","neck"];
|
||
|
||
for (var i=0;i<2;i++){
|
||
try{
|
||
var rndint = parseInt(Math.random()*1000);
|
||
text += words[rndint];
|
||
} catch(e){}
|
||
}
|
||
var possible = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789";
|
||
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
||
while (text.length<LLL){
|
||
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
||
}
|
||
try{
|
||
text = text.replaceAll('AD', 'vDAv'); // avoiding adblockers
|
||
text = text.replaceAll('Ad', 'vdAv');
|
||
text = text.replaceAll('ad', 'vdav');
|
||
text = text.replaceAll('aD', 'vDav');
|
||
} catch(e){errorlog(e);}
|
||
|
||
log(text);
|
||
return text;
|
||
};
|
||
|
||
function hotkeyCheck(event){
|
||
|
||
var value = parseInt(event.key);
|
||
if (value == event.key){
|
||
console.log(value);
|
||
try {
|
||
if (document.querySelector("#containermenu").children[value]){
|
||
document.querySelector("#containermenu").children[value].querySelector("canvas").click();
|
||
document.querySelector("#containermenu").children[value].classList.add("shake");
|
||
setTimeout(function(ele){ele.classList.remove("shake");},500,document.querySelector("#containermenu").children[value]);
|
||
}
|
||
} catch(e){}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
var iframe = null;
|
||
|
||
function loadIframe(){
|
||
|
||
|
||
var additional = "";
|
||
if (password){
|
||
additional = "&password="+password;
|
||
}
|
||
|
||
roomname = sanitizeRoomName(roomname);
|
||
|
||
iframe = document.createElement("iframe");
|
||
var iframeContainer = document.getElementById("iframeContainer");
|
||
iframe.allow = "autoplay;camera;microphone;fullscreen;picture-in-picture;display-capture;";
|
||
|
||
if (roomname){
|
||
var iframesrc = "./index.html?ltb=350&transparent&cleanoutput&director="+roomname+additional+"&b64css="+injectCSS;
|
||
} else {
|
||
roomname = generateString(10);
|
||
var iframesrc = "./index.html?ltb=350&transparent&cleanoutput&director="+roomname+additional;
|
||
}
|
||
|
||
document.title = "Mixer: "+roomname;
|
||
|
||
<!-- var button = document.createElement("button"); -->
|
||
<!-- button.innerHTML = "Refresh list ↻"; -->
|
||
<!-- button.onclick = function(){iframe.contentWindow.postMessage({"getStreamIDs":true}, '*');}; -->
|
||
<!-- button.style.display = "block"; -->
|
||
<!-- button.classList.add("menuButton"); -->
|
||
<!-- document.getElementById("sources").appendChild(button); -->
|
||
|
||
var button = document.createElement("button");
|
||
button.innerHTML = "Settings ⚙︎";
|
||
button.onclick = showSettings;
|
||
button.id = "showSettings";
|
||
button.classList.add("menuButton");
|
||
document.getElementById("sources").appendChild(button);
|
||
|
||
var button = document.createElement("button");
|
||
button.innerHTML = "Switch Modes ↻";
|
||
button.title = "Toggle between director view and scene preview modes";
|
||
button.classList.add("menuButton");
|
||
button.state = false;
|
||
button.dataset.state = button.state;
|
||
button.onclick = function(){
|
||
this.state = !this.state;
|
||
this.dataset.state = this.state;
|
||
iframe.contentWindow.postMessage({"previewMode":this.state, "layout":currentLayout, "bitrate":35, "target": "*"}, '*');
|
||
if (this.state){
|
||
this.innerHTML = "Director View ↻";
|
||
iframe.classList.add("aspectRatio");
|
||
this.title = "Switch to the director room mode";
|
||
} else {
|
||
this.innerHTML = "Scene Preview ↻";
|
||
this.title = "Switch to scene preview mode";
|
||
iframe.classList.remove("aspectRatio");
|
||
}
|
||
|
||
};
|
||
document.getElementById("sources").appendChild(button);
|
||
|
||
|
||
var button = document.createElement("button");
|
||
button.innerHTML = "Add Stream ID";
|
||
button.title = "Create a placeholder for a stream ID; the guest doesn't need to be connected yet.";
|
||
button.classList.add("menuButton");
|
||
//button.state = false;
|
||
button.dataset.state = button.state;
|
||
button.onclick = function(){
|
||
//this.state = !this.state;
|
||
//this.dataset.state = this.state;
|
||
var sid = prompt("What is the stream ID for this invite?");
|
||
if (sid){
|
||
if (sid in streamIDs){
|
||
if (document.getElementById("sid_"+sid)){
|
||
document.getElementById("sid_"+sid).classList.remove("shake");
|
||
setTimeout(function(){document.getElementById("sid_"+sid).classList.add("shake");},10);
|
||
} else {
|
||
updateList();
|
||
}
|
||
} else {
|
||
streamIDs.push(sid);
|
||
updateList();
|
||
if (document.getElementById("sid_"+sid)){
|
||
document.getElementById("sid_"+sid).classList.add("disconnected");
|
||
document.getElementById("sid_"+sid).title = "Not currently connected, but can still be placed";
|
||
}
|
||
}
|
||
}
|
||
};
|
||
button.style.display = "block";
|
||
document.getElementById("sources").appendChild(button);
|
||
|
||
|
||
var button = document.createElement("button");
|
||
button.innerHTML = "Invite Guest";
|
||
button.classList.add("menuButton");
|
||
button.state = false;
|
||
button.dataset.state = button.state;
|
||
button.id = "inviteGuestButton";
|
||
button.onclick = showInviteOptions;
|
||
document.getElementById("sources").appendChild(button);
|
||
|
||
|
||
var a = document.createElement("a");
|
||
a.innerHTML = "Invite Guest Link 📎";
|
||
a.href = "./index.html?room="+roomname+"&broadcast"+additional;
|
||
a.target = "_blank";
|
||
document.getElementById("sources").appendChild(a);
|
||
|
||
var a = document.createElement("a");
|
||
a.innerHTML = "Scene View Link 📎";
|
||
a.href = "./index.html?scene=0&layout=%7B%7D&room="+roomname+additional;
|
||
a.target = "_blank";
|
||
document.getElementById("sources").appendChild(a);
|
||
|
||
|
||
var slots = document.getElementById("col1").children;
|
||
for (var i=0;i<slots.length;i++){
|
||
slots[i].style.backgroundColor = colors[i];
|
||
slots[i].style.opacity = "0.9";
|
||
}
|
||
|
||
//drawAddNewLayout();
|
||
drawAddNewLayout2();
|
||
//drawAutoLayout();
|
||
drawAddNewLayout3();
|
||
|
||
for (var i in savedSession.layouts){
|
||
drawLayout(savedSession.layouts[i]);
|
||
}
|
||
|
||
iframe.src = iframesrc;
|
||
iframeContainer.appendChild(iframe);
|
||
document.getElementById("container").appendChild(iframeContainer);
|
||
|
||
iframe.contentWindow.addEventListener("keydown", hotkeyCheck);
|
||
document.addEventListener("keydown", hotkeyCheck);
|
||
|
||
//////////// LISTEN FOR EVENTS
|
||
|
||
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
|
||
var eventer = window[eventMethod];
|
||
var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message";
|
||
|
||
/// If you have a routing system setup, you could have just one global listener for all iframes instead.
|
||
|
||
eventer(messageEvent, function (e) {
|
||
if (e.source != iframe.contentWindow){return} // reject messages send from other iframes
|
||
|
||
if ("action" in e.data){
|
||
///var outputWindow = document.createElement("div");
|
||
//outputWindow.innerHTML = "event: "+e.data.action+"<br />";
|
||
//outputWindow.style.border="1px dotted black";
|
||
//iframeContainer.appendChild(outputWindow);
|
||
//console.log(e.data.action);
|
||
if (e.data.action === "view-connection"){
|
||
if (e.data.value){
|
||
iframe.contentWindow.postMessage({"getStreamIDs":true}, '*');
|
||
} else if (e.data.streamID){
|
||
for (var i = 0; i < streamIDs.length; i++){
|
||
if (e.data.streamID == streamIDs[i]){
|
||
streamIDs.splice(i,1);
|
||
if (document.getElementById("sid_"+e.data.streamID)){
|
||
document.getElementById("sid_"+e.data.streamID).classList.add("disconnected");
|
||
document.getElementById("sid_"+e.data.streamID).title = "Not currently connected, but can still be placed";
|
||
}
|
||
}
|
||
}
|
||
updateList();
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
console.log(e.data);
|
||
if (e.data.action && (e.data.action == "scene-connected")){
|
||
if (lastLayout && lastLayout.scene == e.data.value){
|
||
iframe.contentWindow.postMessage(lastLayout, '*');
|
||
}
|
||
}
|
||
|
||
if ("streamIDs" in e.data){
|
||
streamIDs = [];
|
||
for (var key in e.data.streamIDs){
|
||
streamIDs.push(key);
|
||
}
|
||
updateList();
|
||
console.log(streamIDs);
|
||
}
|
||
});
|
||
}
|
||
|
||
function removeStorage(cname){
|
||
localStorage.removeItem(cname);
|
||
}
|
||
|
||
function setStorage(cname, cvalue, hours=9999){ // not actually a cookie
|
||
var now = new Date();
|
||
var item = {
|
||
value: cvalue,
|
||
expiry: now.getTime() + (hours * 60 * 60 * 1000),
|
||
};
|
||
try{
|
||
localStorage.setItem(cname, JSON.stringify(item));
|
||
}catch(e){errorlog(e);}
|
||
}
|
||
|
||
function getStorage(cname) {
|
||
try {
|
||
var itemStr = localStorage.getItem(cname);
|
||
} catch(e){
|
||
errorlog(e);
|
||
return;
|
||
}
|
||
if (!itemStr) {
|
||
return "";
|
||
}
|
||
var item = JSON.parse(itemStr);
|
||
var now = new Date();
|
||
if (now.getTime() > item.expiry) {
|
||
localStorage.removeItem(cname);
|
||
return "";
|
||
}
|
||
return item.value;
|
||
}
|
||
|
||
function showSettings(){
|
||
document.getElementById("modal").style.display = "block";
|
||
document.getElementById("modal-content").innerHTML = document.getElementById("sceneSettings").innerHTML;
|
||
}
|
||
|
||
function showInviteOptions(){
|
||
document.getElementById("modal").style.display = "block";
|
||
document.getElementById("modal-content").innerHTML = document.getElementById("inviteOptions").innerHTML;
|
||
|
||
var additional = "";
|
||
if (password){
|
||
additional = "&password="+password;
|
||
}
|
||
|
||
document.querySelectorAll(".roomname").forEach(ele=>{
|
||
ele.innerText = roomname;
|
||
});
|
||
|
||
document.querySelectorAll("a.inviteLink").forEach(ele=>{
|
||
ele.href = "./index.html?room="+roomname+"&broadcast"+additional;
|
||
});
|
||
|
||
|
||
}
|
||
|
||
function addLayout(){
|
||
var layout = prompt("Enter your new layout as a JSON string", '[{"x":0,"y":0,"w":100,"h":100}]');
|
||
layout = JSON.parse(layout);
|
||
console.log(layout);
|
||
drawLayout(layout);
|
||
}
|
||
|
||
function addLayout2(item=false){
|
||
document.getElementById("containermenu").classList.add("hidden");
|
||
iframe.classList.add("hidden");
|
||
document.getElementById("containermenu2").classList.remove("hidden");
|
||
document.getElementById("canvas").classList.remove("hidden");
|
||
try {
|
||
var tar = item.parentNode.querySelector("canvas").sceneName;
|
||
document.getElementById("canvas").sceneName = tar;
|
||
} catch(e){
|
||
addOldElement({});
|
||
addElement();
|
||
}
|
||
}
|
||
|
||
function closeScene(){
|
||
document.getElementById("containermenu").classList.remove("hidden");
|
||
iframe.classList.remove("hidden");
|
||
document.getElementById("containermenu2").classList.add("hidden");
|
||
document.getElementById("canvas").classList.add("hidden");
|
||
}
|
||
|
||
function drawLayout(layoutOriginal, sceneName=false){
|
||
|
||
var layout = [];
|
||
for (var i=0;i<layoutOriginal.length;i++){
|
||
if (!layoutOriginal[i]){
|
||
continue;
|
||
}
|
||
if (!("slot" in layoutOriginal[i])){
|
||
layoutOriginal[i].slot = i;
|
||
}
|
||
layout.push(layoutOriginal[i]);
|
||
}
|
||
|
||
function compare( a, b ) { // sorts layout based on z-index.
|
||
var aa = a.z || 0;
|
||
var bb = b.z || 0;
|
||
if ( aa > bb ){
|
||
return 1;
|
||
}
|
||
if ( aa < bb ){
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
layout.sort(compare);
|
||
|
||
|
||
var canvas = document.createElement('canvas');
|
||
canvas.width="80";
|
||
canvas.height="45";
|
||
|
||
var ctx = canvas.getContext('2d');
|
||
|
||
ctx.beginPath();
|
||
ctx.rect(0, 0, 80, 45);
|
||
ctx.fillStyle = "#000";
|
||
ctx.fill();
|
||
|
||
for (var i=0;i<layout.length;i++){
|
||
|
||
ctx.fillStyle = colors[parseInt(layout[i].slot)];
|
||
ctx.lineWidth = 3;
|
||
var x = layout[i].x*0.8 || 0;
|
||
var y = layout[i].y*0.45 || 0;
|
||
var w = layout[i].w*0.8 || 0;
|
||
var h = layout[i].h*0.45 || 0;
|
||
|
||
ctx.beginPath();
|
||
ctx.rect(x, y, w, h);
|
||
ctx.fill();
|
||
}
|
||
|
||
canvas.layout = JSON.stringify(layout);
|
||
canvas.onclick = remoteActivate;
|
||
|
||
if (slotsNeeded<layout.length){
|
||
slotsNeeded = layout.length;
|
||
for (var i=0;i<slotsNeeded;i++){
|
||
if (!document.querySelector("div[data-slot='"+(i+1)+"']")){
|
||
var emptySlot = document.createElement("div");
|
||
emptySlot.innerHTML = "SLOT "+(i+1);
|
||
emptySlot.classList.add("empty");
|
||
emptySlot.dataset.slot = (i+1)+"";
|
||
emptySlot.style.backgroundColor = colors[i];
|
||
document.getElementById("col1").appendChild(emptySlot);
|
||
}
|
||
}
|
||
}
|
||
|
||
var editButton = document.createElement("button");
|
||
editButton.innerHTML = "Edit";
|
||
editButton.classList.add("editButton");
|
||
|
||
editButton.onclick = function(){
|
||
addLayout2(this);
|
||
addOldElement(JSON.parse(this.parentNode.querySelector("canvas").layout));
|
||
}
|
||
|
||
var setButton = document.createElement("button");
|
||
setButton.innerHTML = "Set";
|
||
setButton.classList.add("setButton");
|
||
|
||
setButton.onclick = function(e){
|
||
remoteActivate(e, setButton.parentNode.querySelector("canvas"));
|
||
}
|
||
|
||
var hotkey = document.createElement("div");
|
||
hotkey.title = "Keyboard hotkey value. Drag elements around to change order.";
|
||
|
||
if (!sceneName){
|
||
sceneName = parseInt(Math.random()*1000000);
|
||
}
|
||
canvas.sceneName = sceneName;
|
||
|
||
var canvasContainer = document.createElement("div");
|
||
canvasContainer.appendChild(editButton);
|
||
canvasContainer.appendChild(setButton);
|
||
canvasContainer.appendChild(canvas);
|
||
canvasContainer.appendChild(hotkey);
|
||
canvasContainer.classList.add("canvasContainer");
|
||
|
||
var eles = document.getElementById("containermenu").children;
|
||
for (var i =0;i<eles.length;i++){ // replace if existing
|
||
var t = eles[i].querySelector("canvas");
|
||
if (t && t.sceneName && (t.sceneName ==sceneName)){
|
||
t.parentNode.parentNode.insertBefore(canvasContainer, t.parentNode);
|
||
t.parentNode.remove();
|
||
return;
|
||
}
|
||
}
|
||
|
||
//if (customlayout){
|
||
// document.getElementById("addlayout").parentNode.insertBefore(canvasContainer, document.getElementById("addlayout"));
|
||
//} else {
|
||
document.getElementById("containermenu").appendChild(canvasContainer);
|
||
//}
|
||
|
||
}
|
||
|
||
function drawAutoLayout(){
|
||
|
||
var canvas = document.createElement('canvas');
|
||
canvas.width="80";
|
||
canvas.height="45";
|
||
var ctx = canvas.getContext('2d');
|
||
var container = document.createElement('div');
|
||
container.classList.add("inline");
|
||
container.appendChild(canvas);
|
||
document.getElementById("containermenu").appendChild(container);
|
||
ctx.beginPath();
|
||
ctx.rect(0, 0, 80, 45);
|
||
ctx.fillStyle = "#000";
|
||
ctx.fill();
|
||
|
||
ctx.fillStyle = "#FFF";
|
||
ctx.font = "15px Arial";
|
||
ctx.fillText(" Clear ", 16, 20);
|
||
ctx.fillText(" Layout ", 12, 37);
|
||
|
||
canvas.layout = false;
|
||
canvas.onclick = remoteActivate;
|
||
}
|
||
|
||
function drawAddNewLayout(){
|
||
|
||
var canvas = document.createElement('canvas');
|
||
canvas.width="80";
|
||
canvas.height="45";
|
||
var ctx = canvas.getContext('2d');
|
||
var container = document.createElement('div');
|
||
container.classList.add("inline");
|
||
container.appendChild(canvas);
|
||
document.getElementById("containermenu").appendChild(container);
|
||
ctx.beginPath();
|
||
ctx.rect(0, 0, 80, 45);
|
||
ctx.fillStyle = "#000";
|
||
ctx.fill();
|
||
|
||
ctx.fillStyle = "#FFF";
|
||
ctx.font = "15px Arial";
|
||
ctx.fillText(" Add ", 20, 20);
|
||
ctx.fillText(" Layout ", 12, 37);
|
||
//canvas.id = "addlayout";
|
||
canvas.layout = false;
|
||
canvas.onclick = addLayout;
|
||
var hotkey = document.createElement('div');
|
||
hotkey.title = "Keyboard hotkey value. Drag elements around to change order.";
|
||
container.appendChild(hotkey);
|
||
}
|
||
|
||
|
||
function drawAddNewLayout2(){
|
||
|
||
var canvas = document.createElement('canvas');
|
||
canvas.width="80";
|
||
canvas.height="45";
|
||
var ctx = canvas.getContext('2d');
|
||
var container = document.createElement('div');
|
||
container.classList.add("inline");
|
||
container.appendChild(canvas);
|
||
document.getElementById("containermenu").appendChild(container);
|
||
ctx.beginPath();
|
||
ctx.rect(0, 0, 80, 45);
|
||
ctx.fillStyle = "#000";
|
||
ctx.fill();
|
||
|
||
ctx.fillStyle = "#FFF";
|
||
ctx.font = "15px Arial";
|
||
ctx.fillText(" Create ", 12, 20);
|
||
ctx.fillText(" Layout ", 12, 37);
|
||
//canvas.id = "addlayout";
|
||
canvas.layout = {};
|
||
canvas.onclick = addLayout2;
|
||
canvas.title = "Create a new custom layout, with the visual scene editor.";
|
||
var hotkey = document.createElement('div');
|
||
hotkey.title = "Keyboard hotkey value. Drag elements around to change order.";
|
||
container.appendChild(hotkey);
|
||
}
|
||
|
||
function drawAddNewLayout3(){
|
||
|
||
var canvas = document.createElement('canvas');
|
||
canvas.width="80";
|
||
canvas.height="45";
|
||
var ctx = canvas.getContext('2d');
|
||
var container = document.createElement('div');
|
||
container.classList.add("inline");
|
||
container.appendChild(canvas);
|
||
document.getElementById("containermenu").appendChild(container);
|
||
ctx.beginPath();
|
||
ctx.rect(0, 0, 80, 45);
|
||
ctx.fillStyle = "#000";
|
||
ctx.fill();
|
||
|
||
ctx.fillStyle = "#FFF";
|
||
ctx.font = "15px Arial";
|
||
ctx.fillText(" Auto ", 18, 20);
|
||
ctx.fillText(" Mix All ", 13, 37);
|
||
//canvas.id = "addlayout";
|
||
canvas.layout = false;
|
||
canvas.onclick = remoteActivate;
|
||
canvas.title = "This layout will auto-mix all available videos into a single dynamic layout.";
|
||
var hotkey = document.createElement('div');
|
||
hotkey.title = "Keyboard hotkey value. Drag elements around to change order.";
|
||
container.appendChild(hotkey);
|
||
}
|
||
|
||
function pullUp(event){
|
||
this.parentNode.zIndex = parseInt(this.parentNode.zIndex || 0) + 1;
|
||
this.parentNode.style.opacity = "0.9";
|
||
this.parentNode.style.zIndex=this.parentNode.zIndex;
|
||
this.parentNode.dimensions.innerHTML = parseInt(this.parentNode.style.width) +"x"+parseInt(this.parentNode.style.height);
|
||
this.parentNode.dimensions.innerHTML += " : " + parseInt(this.parentNode.style.left) +"x"+parseInt(this.parentNode.style.top);
|
||
this.parentNode.dimensions.innerHTML += " , layer: "+parseInt(this.parentNode.style.zIndex);
|
||
|
||
}
|
||
|
||
function pushDown(event){
|
||
this.parentNode.zIndex = parseInt(this.parentNode.zIndex || 0) - 1;
|
||
if (this.parentNode.zIndex<0){
|
||
this.parentNode.zIndex=0;
|
||
this.parentNode.style.opacity = "1.0";
|
||
} else {
|
||
this.parentNode.style.opacity = "0.9";
|
||
}
|
||
this.parentNode.style.zIndex=this.parentNode.zIndex;
|
||
this.parentNode.dimensions.innerHTML = parseInt(this.parentNode.style.width) +"x"+parseInt(this.parentNode.style.height);
|
||
this.parentNode.dimensions.innerHTML += " : " + parseInt(this.parentNode.style.left) +"x"+parseInt(this.parentNode.style.top);
|
||
this.parentNode.dimensions.innerHTML += " , layer: "+parseInt(this.parentNode.style.zIndex);
|
||
}
|
||
|
||
function addOldElement(object){
|
||
document.getElementById("canvas").innerHTML = "";
|
||
|
||
var hh = 720;
|
||
var ww = parseInt(1280 * (aspectRatio/(16/9)));
|
||
|
||
document.getElementById('canvas').style.width = ww+"px";
|
||
document.getElementById('canvas').style.height = hh+"px";
|
||
|
||
|
||
for (var i=0;i<object.length;i++){
|
||
if (object[i] == null){continue;}
|
||
var slot = parseInt(object[i].slot) || i;
|
||
<!-- ele.w = parseInt(compute.width)/1280*100; -->
|
||
<!-- ele.h = parseInt(compute.height)/720*100; -->
|
||
<!-- ele.x = parseInt(compute.left)/1280*100; -->
|
||
<!-- ele.y = parseInt(compute.top)/720*100; -->
|
||
|
||
<!-- ele.z = object[i].zIndex; -->
|
||
<!-- ele.bg = object[i].backgroundColor; -->
|
||
<!-- ele.bt = object[i].borderThickness; -->
|
||
<!-- ele.bc = object[i].borderColor; -->
|
||
<!-- ele.bm = object[i].backgroundMedia; -->
|
||
<!-- ele.margin = object[i].margin; -->
|
||
<!-- ele.r = object[i].rounded; -->
|
||
<!-- ele.m = object[i].muted; -->
|
||
|
||
var color = colors[slot];
|
||
var container = document.createElement("div");
|
||
|
||
container.className = "widget ui-widget-content draggable resizable";
|
||
container.slot = slot;
|
||
container.cover = object[i].cover || false;
|
||
container.zIndex = parseInt(object[i].z) || 0;
|
||
//container.backgroundColor = object[i].backgroundColor || "#000";
|
||
container.borderThickness = object[i].borderThickness || 0;
|
||
container.animated = object[i].animated || 0;
|
||
container.borderColor = object[i].borderColor || "#000";
|
||
container.backgroundMedia = object[i].backgroundMedia || "";
|
||
container.defaultStreamID = object[i].defaultStreamID || "";
|
||
container.margin = object[i].margin || 0;
|
||
container.muted = object[i].muted || false;
|
||
container.rounded = object[i].rounded || 0;
|
||
|
||
var hh = 720;
|
||
var ww = 1280 * (aspectRatio/(16/9));
|
||
|
||
var yoffset = object[i].y*hh/100;
|
||
var xoffset =object[i].x*ww/100;
|
||
var w = object[i].w*ww/100;
|
||
var h = object[i].h*hh/100;
|
||
|
||
container.style = "z-index:"+container.zIndex+";left:"+xoffset+"px;top:"+yoffset+"px;width:"+w+"px;height:"+h+"px;background-color:"+color+";";
|
||
|
||
var h3 = document.createElement("h3");
|
||
h3.className = "ui-widget-header";
|
||
h3.innerHTML = "drag/resize me";
|
||
container.appendChild(h3);
|
||
|
||
var button = document.createElement("button");
|
||
//button.className = "ui-widget-header";
|
||
button.innerHTML = "Settings";
|
||
button.onclick = settings;
|
||
container.appendChild(button);
|
||
|
||
var button = document.createElement("button");
|
||
//button.className = "ui-widget-header";
|
||
button.innerHTML = "Delete";
|
||
button.onclick = deleteElement;
|
||
container.appendChild(button);
|
||
|
||
var button = document.createElement("button");
|
||
//button.className = "ui-widget-header";
|
||
button.innerHTML = "Pull Front";
|
||
button.onclick = pullUp;
|
||
container.appendChild(button);
|
||
|
||
var button = document.createElement("button");
|
||
//button.className = "ui-widget-header";
|
||
button.innerHTML = "Push Back";
|
||
button.onclick = pushDown;
|
||
container.appendChild(button);
|
||
container.dimensions = dimensions;
|
||
var dimensions = document.createElement("div");
|
||
container.dimensions = dimensions;
|
||
dimensions.innerHTML = parseInt(container.style.width) +"x"+parseInt(container.style.height);
|
||
dimensions.innerHTML += " : " + parseInt(container.style.left) +"x"+parseInt(container.style.top);
|
||
dimensions.innerHTML += " , layer: "+parseInt(container.style.zIndex);
|
||
dimensions.style = "position:absolute;left:10px;bottom:0;max-width:250px;height:20px;";
|
||
|
||
container.appendChild(dimensions);
|
||
container.ondrag = function(e){
|
||
this.dimensions.innerHTML = parseInt(this.style.width) +"x"+parseInt(this.style.height);
|
||
this.dimensions.innerHTML += " : " + parseInt(this.style.left) +"x"+parseInt(this.style.top);
|
||
this.dimensions.innerHTML += " , layer: "+parseInt(this.style.zIndex);
|
||
}
|
||
container.onresize = function(e){
|
||
this.dimensions.innerHTML = parseInt(this.style.width) +"x"+parseInt(this.style.height);
|
||
this.dimensions.innerHTML += " : " + parseInt(this.style.left) +"x"+parseInt(this.style.top);
|
||
this.dimensions.innerHTML += " , layer: "+parseInt(this.style.zIndex);
|
||
}
|
||
|
||
document.getElementById("canvas").appendChild(container);
|
||
|
||
$(function(){
|
||
$(".draggable").draggable({ snap: true , grid: [ 10,10 ] });
|
||
});
|
||
$(function(){
|
||
$(".resizable").resizable({ snap: true , grid: [ 10, 10] });
|
||
});
|
||
}
|
||
}
|
||
|
||
function addElement(x=false,y=false){
|
||
|
||
var eles = document.querySelectorAll(".widget");
|
||
|
||
var indexs = [];
|
||
for (var i=0;i<eles.length;i++){
|
||
indexs.push(parseInt(eles[i].slot));
|
||
}
|
||
|
||
indexs.sort();
|
||
var slot = 0;
|
||
|
||
for (var i=0;i<indexs.length;i++){
|
||
if (slot!=indexs[i]){
|
||
break;
|
||
} else {
|
||
slot+=1;
|
||
}
|
||
}
|
||
|
||
var color = colors[slot];
|
||
var container = document.createElement("div");
|
||
container.className = "widget ui-widget-content draggable resizable";
|
||
container.slot = slot;
|
||
|
||
var yoffset = 20*(slot+1);
|
||
var xoffset = 20*(slot+1);
|
||
|
||
container.style = "z-Index:10;left:"+xoffset+"px;top:"+yoffset+"px;width:640px;height:360px;background-color:"+color+";";
|
||
container.zIndex = 10;
|
||
var h3 = document.createElement("h3");
|
||
h3.className = "ui-widget-header";
|
||
h3.innerHTML = "drag/resize me";
|
||
container.appendChild(h3);
|
||
|
||
var button = document.createElement("button");
|
||
//button.className = "ui-widget-header";
|
||
button.innerHTML = "Settings";
|
||
button.onclick = settings;
|
||
container.appendChild(button);
|
||
|
||
var button = document.createElement("button");
|
||
//button.className = "ui-widget-header";
|
||
button.innerHTML = "Delete";
|
||
button.onclick = deleteElement;
|
||
container.appendChild(button);
|
||
|
||
var button = document.createElement("button");
|
||
//button.className = "ui-widget-header";
|
||
button.innerHTML = "Pull Front";
|
||
button.onclick = pullUp;
|
||
container.appendChild(button);
|
||
|
||
var button = document.createElement("button");
|
||
//button.className = "ui-widget-header";
|
||
button.innerHTML = "Push Back";
|
||
button.onclick = pushDown;
|
||
container.appendChild(button);
|
||
|
||
var dimensions = document.createElement("div");
|
||
container.dimensions = dimensions;
|
||
dimensions.innerHTML = parseInt(container.style.width) +"x"+parseInt(container.style.height);
|
||
dimensions.innerHTML += " : " + parseInt(container.style.left) +"x"+parseInt(container.style.top);
|
||
dimensions.style = "position:absolute;left:10px;bottom:0;max-width:250px;height:20px;";
|
||
dimensions.innerHTML += " , layer: "+parseInt(container.style.zIndex);
|
||
|
||
container.appendChild(dimensions);
|
||
container.ondrag = function(e){
|
||
this.dimensions.innerHTML = parseInt(this.style.width) +"x"+parseInt(this.style.height);
|
||
this.dimensions.innerHTML += " : " + parseInt(this.style.left) +"x"+parseInt(this.style.top);
|
||
this.dimensions.innerHTML += " , layer: "+parseInt(this.style.zIndex);
|
||
|
||
}
|
||
container.onresize = function(e){
|
||
this.dimensions.innerHTML = parseInt(this.style.width) +"x"+parseInt(this.style.height);
|
||
this.dimensions.innerHTML += " : " + parseInt(this.style.left) +"x"+parseInt(this.style.top);
|
||
this.dimensions.innerHTML += " , layer: "+parseInt(this.style.zIndex);
|
||
|
||
}
|
||
|
||
document.getElementById("canvas").appendChild(container);
|
||
|
||
container.style.zIndex = "10";
|
||
container.zIndex = 10;
|
||
|
||
$(function(){
|
||
$(".draggable").draggable({ snap: true , grid: [ 10,10 ] });
|
||
});
|
||
$(function(){
|
||
$(".resizable").resizable({ snap: true , grid: [ 10, 10] });
|
||
});
|
||
}
|
||
|
||
function remoteActivate(event, ele=false){
|
||
if (!ele){
|
||
ele = this;
|
||
}
|
||
if (ele.layout){
|
||
var layout = JSON.parse(ele.layout);
|
||
console.log(layout);
|
||
var combined = {};
|
||
for (var i=0;i<layout.length;i++){
|
||
//layout[i].z = i;
|
||
if (!layout[i]){continue;}
|
||
if (!("slot" in layout[i])){
|
||
//console.log("no slot");
|
||
//if (!(null in combined)){
|
||
// combined[null] = [];
|
||
//}
|
||
//combined[null].push(layout[i]);
|
||
continue;
|
||
}
|
||
try {
|
||
var stream = document.querySelector(".thing[data-slot='"+(parseInt(layout[i].slot)+1)+"'");
|
||
} catch(e){
|
||
errorlog(e);
|
||
continue;
|
||
}
|
||
console.log(stream);
|
||
console.log(i);
|
||
console.log(layout);
|
||
|
||
if (!stream){
|
||
if (layout[i].defaultStreamID){
|
||
if (!document.querySelector(".thing[data-slot][data-sid='"+layout[i].defaultStreamID+"']")){
|
||
combined[layout[i].defaultStreamID] = layout[i];
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
combined[stream.dataset.sid] = layout[i];
|
||
}
|
||
} else {
|
||
var layout = null;
|
||
var combined = false;
|
||
}
|
||
console.log(combined);
|
||
currentLayout = combined; // global current state
|
||
lastLayout = {"scene":"0", "layout":combined};
|
||
iframe.contentWindow.postMessage({"scene":"0", "layout":combined}, '*');
|
||
var layoutButtons = document.querySelectorAll(".pressed");
|
||
for (var i = 0;i<layoutButtons.length;i++){
|
||
layoutButtons[i].classList.remove("pressed");
|
||
}
|
||
ele.parentNode.classList.add("pressed");
|
||
}
|
||
|
||
function deleteElement(event){
|
||
this.parentNode.remove();
|
||
}
|
||
|
||
function settings(){
|
||
var parent = this.parentNode;
|
||
|
||
if (parent.setting){
|
||
parent.setting.classList.toggle("hidden");
|
||
return;
|
||
}
|
||
errorlog(parent);
|
||
|
||
var setEle = document.createElement("div");
|
||
parent.appendChild(setEle);
|
||
parent.setting = setEle;
|
||
setEle.className = "settings";
|
||
setEle.innerHTML = "";
|
||
|
||
setEle.style.left = 0;
|
||
setEle.style.top = "63px";
|
||
setEle.style.margin = "5px";
|
||
setEle.style.padding = "10px";
|
||
|
||
var br = document.createElement("br");
|
||
setEle.appendChild(br);
|
||
var label = document.createElement("label");
|
||
label.innerHTML = "Background Image (URL)";
|
||
setEle.appendChild(label);
|
||
var input = document.createElement("input");
|
||
input.style.width = "200px";
|
||
setEle.appendChild(input);
|
||
input.value = parent.backgroundMedia || "";
|
||
input.onchange = function(){
|
||
parent.backgroundMedia = this.value;
|
||
}
|
||
|
||
var br = document.createElement("br");
|
||
setEle.appendChild(br);
|
||
var label = document.createElement("label");
|
||
label.innerHTML = "Default Stream ID";
|
||
label.title = "If the slot is empty, this will be the default stream ID used.";
|
||
setEle.appendChild(label);
|
||
var input = document.createElement("input");
|
||
input.style.width = "200px";
|
||
setEle.appendChild(input);
|
||
input.value = parent.defaultStreamID || "";
|
||
input.onchange = function(){
|
||
parent.defaultStreamID = this.value;
|
||
}
|
||
|
||
<!-- var br = document.createElement("br"); -->
|
||
<!-- setEle.appendChild(br); -->
|
||
<!-- var label = document.createElement("label"); -->
|
||
<!-- label.innerHTML = "Hex Color"; -->
|
||
<!-- setEle.appendChild(label); -->
|
||
<!-- var input = document.createElement("input"); -->
|
||
<!-- input.style.width = "80px"; -->
|
||
<!-- setEle.appendChild(input); -->
|
||
<!-- input.value = parent.backgroundColor || "#000"; -->
|
||
<!-- input.onchange = function(){ -->
|
||
<!-- parent.backgroundColor = this.value; -->
|
||
<!-- } -->
|
||
|
||
var br = document.createElement("br");
|
||
setEle.appendChild(br);
|
||
var label = document.createElement("label");
|
||
label.innerHTML = "Border Thickness (px)";
|
||
setEle.appendChild(label);
|
||
var input = document.createElement("input");
|
||
input.type = "number";
|
||
input.style.width = "80px";
|
||
setEle.appendChild(input);
|
||
input.value = parent.borderThickness || 0;
|
||
input.onchange = function(){
|
||
parent.borderThickness = this.value;
|
||
}
|
||
|
||
var br = document.createElement("br");
|
||
setEle.appendChild(br);
|
||
var label = document.createElement("label");
|
||
label.innerHTML = "Margin (px)";
|
||
setEle.appendChild(label);
|
||
var input = document.createElement("input");
|
||
input.type = "number";
|
||
input.style.width = "80px";
|
||
setEle.appendChild(input);
|
||
input.value = parent.margin || "0";
|
||
input.onchange = function(){
|
||
parent.margin = this.value;
|
||
}
|
||
|
||
var br = document.createElement("br");
|
||
setEle.appendChild(br);
|
||
var label = document.createElement("label");
|
||
label.innerHTML = "Border/Background Color";
|
||
setEle.appendChild(label);
|
||
var input = document.createElement("input");
|
||
input.type = "text";
|
||
input.style.width = "80px";
|
||
setEle.appendChild(input);
|
||
input.value = parent.borderColor || "#000";
|
||
input.onchange = function(){
|
||
parent.borderColor = this.value;
|
||
}
|
||
|
||
var br = document.createElement("br");
|
||
setEle.appendChild(br);
|
||
var label = document.createElement("label");
|
||
label.innerHTML = "Rounded Edges (px)";
|
||
setEle.appendChild(label);
|
||
var input = document.createElement("input");
|
||
input.type = "number";
|
||
input.style.width = "80px";
|
||
setEle.appendChild(input);
|
||
input.value = parent.rounded || 0;
|
||
input.onchange = function(){
|
||
parent.rounded = this.value;
|
||
}
|
||
|
||
var br = document.createElement("br");
|
||
setEle.appendChild(br);
|
||
var br = document.createElement("br");
|
||
setEle.appendChild(br);
|
||
var label = document.createElement("label");
|
||
label.innerHTML = "Media fully cover area?" ;
|
||
setEle.appendChild(label);
|
||
var checkbox = document.createElement("input");
|
||
checkbox.type = "checkbox";
|
||
setEle.appendChild(checkbox);
|
||
checkbox.checked = parent.cover || false;
|
||
checkbox.onchange = function(){
|
||
parent.cover = this.checked;
|
||
}
|
||
|
||
var br = document.createElement("br");
|
||
setEle.appendChild(br);
|
||
var br = document.createElement("br");
|
||
setEle.appendChild(br);
|
||
var label = document.createElement("label");
|
||
label.innerHTML = "Animated transitions";
|
||
setEle.appendChild(label);
|
||
var checkbox = document.createElement("input");
|
||
checkbox.type = "checkbox";
|
||
setEle.appendChild(checkbox);
|
||
if (parent.animated){
|
||
checkbox.checked = true;
|
||
}
|
||
checkbox.onchange = function(){
|
||
parent.animated = this.checked;
|
||
}
|
||
|
||
|
||
var br = document.createElement("br");
|
||
setEle.appendChild(br);
|
||
var br = document.createElement("br");
|
||
setEle.appendChild(br);
|
||
var button = document.createElement("button");
|
||
button.innerHTML = "OK";
|
||
setEle.appendChild(button);
|
||
button.onclick = function(){
|
||
setEle.classList.add("hidden");
|
||
}
|
||
setEle.classList.remove("hidden");
|
||
}
|
||
|
||
function copyJSON(){
|
||
var layout = [];
|
||
var pos = document.getElementById("canvas").getBoundingClientRect();
|
||
var bodyRect = document.body.getBoundingClientRect();
|
||
|
||
var hh = parseInt(document.getElementById("canvas").style.height);
|
||
var ww = parseInt(document.getElementById("canvas").style.width);
|
||
|
||
var eles = document.querySelectorAll(".widget");
|
||
for (var i=0;i<eles.length;i++){
|
||
console.log(eles);
|
||
var compute = window.getComputedStyle(eles[i]);
|
||
var ele = {};
|
||
ele.w = parseFloat(compute.width)/ww*100;
|
||
ele.h = parseFloat(compute.height)/hh*100;
|
||
ele.x = parseFloat(compute.left)/ww*100;
|
||
ele.y = parseFloat(compute.top)/hh*100;
|
||
|
||
try {
|
||
ele.slot = parseInt(eles[i].slot) || i;
|
||
ele.cover = eles[i].cover || false;
|
||
ele.zIndex = parseInt(eles[i].zIndex) || 0;
|
||
|
||
//ele.backgroundColor = eles[i].backgroundColor || "#000";
|
||
ele.borderThickness = parseInt(eles[i].borderThickness) || 0;
|
||
ele.animated = eles[i].animated || 0;
|
||
ele.borderColor = eles[i].borderColor || "#000";
|
||
ele.backgroundMedia = eles[i].backgroundMedia || "";
|
||
ele.defaultStreamID = eles[i].defaultStreamID || "";
|
||
ele.margin = parseInt(eles[i].margin) || 0;
|
||
ele.rounded = parseInt(eles[i].rounded) || 0;
|
||
ele.muted = eles[i].muted || false;
|
||
} catch(e){errorlog(e);}
|
||
layout.push(ele);
|
||
}
|
||
var combined = {};
|
||
for (var i=0;i<layout.length;i++){
|
||
//layout[i].z = i;
|
||
if (!layout[i]){continue;}
|
||
if (!("slot" in layout[i])){
|
||
//console.log("no slot");
|
||
//if (!(null in combined)){
|
||
// combined[null] = [];
|
||
//}
|
||
//combined[null].push(layout[i]);
|
||
continue;
|
||
}
|
||
try {
|
||
var stream = document.querySelector(".thing[data-slot='"+(parseInt(layout[i].slot)+1)+"'");
|
||
} catch(e){
|
||
errorlog(e);
|
||
continue;
|
||
}
|
||
console.log(stream);
|
||
console.log(i);
|
||
console.log(layout);
|
||
if (!stream){
|
||
if (layout[i].defaultStreamID){
|
||
if (!document.querySelector(".thing[data-slot][data-sid='"+layout[i].defaultStreamID+"']")){
|
||
combined[layout[i].defaultStreamID] = layout[i];
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
combined[stream.dataset.sid] = layout[i];
|
||
}
|
||
prompt("Layout as URL-encoded JSON. StreamIDs are based on current and default values.", encodeURIComponent(JSON.stringify(combined)));
|
||
}
|
||
|
||
function saveScene(makenew=false){
|
||
var scene = [];
|
||
|
||
var hh = parseInt(document.getElementById("canvas").style.height);
|
||
var ww = parseInt(document.getElementById("canvas").style.width);
|
||
|
||
var eles = document.querySelectorAll(".widget");
|
||
for (var i=0;i<eles.length;i++){
|
||
console.log(eles);
|
||
var compute = window.getComputedStyle(eles[i]);
|
||
var ele = {};
|
||
ele.w = parseFloat(eles[i].style.width)/ww*100;
|
||
ele.h = parseFloat(eles[i].style.height)/hh*100;
|
||
ele.x = parseFloat(eles[i].style.left)/ww*100;
|
||
ele.y = parseFloat(eles[i].style.top)/hh*100;
|
||
|
||
try {
|
||
ele.slot = parseInt(eles[i].slot) || i;
|
||
ele.cover = eles[i].cover || false;
|
||
ele.zIndex = parseInt(eles[i].zIndex) || 0;
|
||
|
||
//ele.backgroundColor = eles[i].backgroundColor || "#000";
|
||
ele.borderThickness = parseInt(eles[i].borderThickness) || 0;
|
||
ele.animated = eles[i].animated || 0;
|
||
ele.borderColor = eles[i].borderColor || "#000";
|
||
ele.backgroundMedia = eles[i].backgroundMedia || "";
|
||
ele.defaultStreamID = eles[i].defaultStreamID || "";
|
||
ele.margin = parseInt(eles[i].margin) || 0;
|
||
ele.rounded = parseInt(eles[i].rounded) || 0;
|
||
ele.muted = eles[i].muted || false;
|
||
} catch(e){errorlog(e);}
|
||
scene.push(ele);
|
||
//scene[sid] = ele;
|
||
}
|
||
console.log(scene);
|
||
|
||
var sceneName = document.getElementById("canvas").sceneName || parseInt(Math.random()*1000000);
|
||
console.log("'sceneName: "+sceneName);
|
||
if (makenew){
|
||
drawLayout(scene, false);
|
||
} else {
|
||
drawLayout(scene, sceneName);
|
||
}
|
||
|
||
saveSession();
|
||
}
|
||
|
||
function removeScene(){
|
||
var sceneName = document.getElementById("canvas").sceneName || false;
|
||
if (sceneName){
|
||
var eles = document.getElementById("containermenu").children;
|
||
for (var i =0;i<eles.length;i++){ // replace if existing
|
||
var t = eles[i].querySelector("canvas");
|
||
if (t && t.sceneName && (t.sceneName ==sceneName)){
|
||
t.parentNode.remove();
|
||
break
|
||
}
|
||
}
|
||
}
|
||
closeScene();
|
||
saveSession();
|
||
}
|
||
|
||
function saveSession(){
|
||
var layouts = document.querySelectorAll(".canvasContainer>canvas");
|
||
savedSession.layouts = [];
|
||
for (var i=0;i<layouts.length;i++){
|
||
savedSession.layouts.push(JSON.parse(layouts[i].layout));
|
||
}
|
||
setStorage("savedSession", JSON.stringify(savedSession));
|
||
console.log(getStorage("savedSession"));
|
||
}
|
||
|
||
function changeAspectRatio(ar, button){
|
||
document.querySelectorAll(".aspectbutton").forEach(ele=>{
|
||
if (ele == button){return;}
|
||
ele.checked = false;
|
||
ele.value = false;
|
||
});
|
||
aspectRatio = ar;
|
||
document.documentElement.style.setProperty('--aspect-ratio', ar);
|
||
}
|
||
|
||
let modal = document.querySelector("#modal");
|
||
let closeBtn = document.querySelector(".close-btn");
|
||
closeBtn.onclick = function(){
|
||
modal.style.display = "none";
|
||
}
|
||
window.onclick = function(e){
|
||
if (e.target == modal){
|
||
modal.style.display = "none";
|
||
}
|
||
}
|
||
|
||
if (roomname){
|
||
loadIframe();
|
||
} else {
|
||
document.getElementById("welcomeWindow").style.display = "block";
|
||
}
|
||
</script>
|
||
</body>
|
||
</html> |