The full featured, canvas-based Javascript console for A-Frame. Connect a bluetooth controller and enter commands, or just view your logs live, scrolling with thumbstick.
pixel-width
)core:warn blah blah
where core:warn
is orange)help
superkeyboard
and use it with the console, the default super keyboard lacks keys for symbols needed to write code. Pull request welcome to add a custom keyboard! That said, coding is much nicer on a real keyboard, so I recommend using a bluetooth keyboard anyways.https://user-images.githubusercontent.com/6391152/185741975-a4cf08da-a521-46db-92f2-db312cac0163.mp4
Also: check out vr-super-stats to see live stats while in-headset.
By default it will intercept console.log/warn/error, and print stack traces on error. You can also manually print to the console with the writeToCanvas()
method.
For the basic use case, literally just add the source:
<head>
<!-- add aframe first, then add this component -->
<script src="https://cdn.jsdelivr.net/gh/kylebakerio/a-console@1.0.2/a-console.js"></script>
</head>
and then, this line to your scene:
<a-console position="0 1.5 -2"></a-console>
You can easily attach it to your controller if you like:
<a-entity id="left-hand" class="local-hand" laser-controls="hand:left;">
<a-console thumbstick-scrolling="#left-hand" font-size="35" position="0 .13 -.36" scale=".33 .33 .33" rotation="-70.7 -1.77"></a-console>
</a-entity>
Notice the thumbstick-scrolling option. By supplying the selector for an entity that emits thumbstickmoved
events, those events then get picked up and used to scroll through console history
If you want to connect a keyboard and type input to the console, just add keyboard-events="true"
:
<a-console keyboard-events="true" position="0 1.5 -2"></a-console>
Modifying the height/width/resolution/font size are all easy and will all be easily handled:
<a-console height="2.24" font-size="34" width="3.91" pixel-width="2160" position="0 1.5 -2"></a-console>
I suggest you do it like this:
You can ignore these settings and just get a basic panel with decent defaults, or fit it into your world wherever you like. It's recommended you attach it to a controller rather than your head if you want to bring it around with you, though.
An example:
"I want a 16:9 1080p screen positioned vertically" So: // set height/width to 16:9, with the long side being height height: 1.6 width: .9 // set pixels for the width side: pixel-width: 1080 // how many pixels go on the width (.9) side; 1920 per 1.6 will be auto-calculated to keep pixels square, so we don't have to specify that font-size: 25 // whatever is readable at the geometry scale you picked
while using the canvas means this app does not add draw calls and so should have relatively low impact on fps, no attempts have been made at all to make it sensitive to garbage collection--it churns through thousands of arrays and objects as new lines are added. premature optimization is the root of all evil, so making it work was the priority.
always check the update() function, it may be that some settings only work on init()
AFRAME.registerPrimitive('a-console', extendDeep({}, meshMixin, {
defaultComponents: {
geometry: {primitive: 'plane', width:1.6*.666, height:2.56*.666}, // 1920 x 1200, / 3 for more manageable size
material: {side: 'double'},
console: {},
},
mappings: {
height: 'geometry.height',
width: 'geometry.width',
'font-size': 'console.fontSize',
// font-family MUST be a monospace font, or expect things to break :)
'font-family': 'console.fontFamily',
'text-color': 'console.textColor',
'background-color': 'console.backgroundColor',
// side: 'material.side',
'pixel-width': 'console.canvasWidth',
'pixel-height': 'console.canvasHeight',
// pixel-height not necessary or looked at unless allow-custom-aspect-ratio is true
'allow-custom-aspect-ratio': 'console.pixelRatioOverride',
'skip-intro': 'console.skipIntroAnimation',
'font-size': 'console.fontSize',
// always in 'pixels' (px), supply '18' to get '18px'
// specify how many input entries to save for resizing/scrolling
'history': 'console.history',
// by default includes log/warn/error, but you could specify that you
// only want errors if desired by setting this to ='error'
'capture-console': 'console.captureConsole',
// fill screen with colored timestamps
'demo': 'console.demo',
// inject 3d virtual keyboard (current iteration lacks symbols, only has letters+numbers)
'inject-keyboard': 'console.injectKeyboard',
// which cursor to use to select keys on the virtual keyboard
'use-cursor': 'console.kbCursor',
// accept actual keyboard events themselves (e.g. from bluetooth keyboard)
'keyboard-events': 'console.keyboardEventsInput',
'thumbstick-scrolling': 'console.thumbstickScrolling',
}
}));
AFRAME.registerComponent('console', { dependencies: ['geometry', 'material'], schema: { fontSize: {default: 20, type: 'number'}, fontFamily: {default: 'monospace', type: 'string'}, textColor: {default: 'green', type: 'color'}, inputColor: {default: 'white', type: 'color'}, returnColor: {default: 'orange', type: 'color'}, backgroundColor: {default: 'black', type: 'color'},
// how much historical input to store
history: { default: 2000, type:'number'},
// canvas dimensions corresponsd to screen resolution, geometry to screen size.
// 2560x1600 = 2k 16:10 ratio screen, vertically.
// note that specified geometry will override this setting, and only width will be observed,
// unless pixelRatioOverride = true, to keep pixels square by default, and allow
// resizing screen without distortion.
canvasWidth: {default: 1600, type: 'number'},
canvasHeight: {default: 2560, type: 'number'},
pixelRatioOverride: {default: false, type: 'bool'},
captureConsole: {default: ['log','warn','error'], type: 'array'},
// ^could also specify debug, info
captureConsoleColors: {default: ["",'yellow','red'], type: 'array'},
captureStackTraceFor: {default: ['error'], type:'array'},
showStackTraces: {default: true, type:'bool'},
skipIntroAnimation: {default: false, type: 'bool'},
introLineDelay: {default: 75, type:'number'},
keepLogo: {default: false, type:'bool'},
demo: {default: false, type: 'bool'},
// inject aframe-super-keyboard
// note: default keyboard lacks symbols needed for most code stuff
// pull request for custom keyboard with symbols is welcome!
injectKeyboard: {default: false, type: 'bool'},
kbCursor: {default: '[cursor]', type:'selector'},
// ^specify raycaster that can interact with the VR keyboard
// use events from physical keyboard:
keyboardEventsInput: {default: false, type: 'bool'},
// helpful stuff for working with aframe input
addKeyboardHelpers: {default: true, type: 'bool'},
saveCommandHistory: {default: true, type: 'bool'},
thumbstickScrolling: {default: '', type: 'selector'}
},
Check out index.html for some examples.
## further things that I might add or accept pull requests for:
- when scrolling, stop new content from causing auto-scroll down
- inclusive/exclusive filter
- make stack traces toggle/revealable
- per-line font size (would be very easy to implement, but low priority, not sure anyone would use this feature)
- expanding support for the [console object API](https://developer.mozilla.org/en-US/docs/Web/API/console) (debug and info should 'just work' if you add them in settings)
- single-page mode (so, instead of adding to history, a way to keep modifying the visible lines, enabling text-GUI stuff a-la HTOP, etc.) (easy to implement with current design, but probably no demand for it; did something similar with keyboard support)
- allow JSON stringify custom settings (not hard to implement, probably no demand for it)