Przeglądaj źródła

Add FullScreenPlugin and example, other minor fixes.

master
Palash Bansal 2 lat temu
rodzic
commit
e7d710ade9
No account linked to committer's email address

+ 1
- 1
examples/examples-utils/simple-code-preview.mjs Wyświetl plik

@@ -17,7 +17,7 @@ setupCodePreview(
scripts,
scripts.map(s=>s.textContent ? 'js' : s.split('.').pop()), // title
scripts.map(s=>(typeof s === 'string' && s.endsWith('.js')) ? s : 'https://github.com/repalash/threepipe/tree/master/examples/'+ window.location.pathname.split('/examples/').pop().replace('index.html', '')+(s.textContent ? 'index.html' : s)), // todo: github link
(c) => replaceImports(c).replaceAll(` from '../`, ` from 'https://threepipe.org/examples/`),
(c) => '// Threepipe example: ' + window.location.href + '\n' + replaceImports(c).replaceAll(` from '../`, ` from 'https://threepipe.org/examples/`),
{
title: 'ThreePipe: ' + document.title,
css,

+ 35
- 0
examples/fullscreen-plugin/index.html Wyświetl plik

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Fullscreen Plugin</title>
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

<script type="importmap">
{
"imports": {
"threepipe": "./../../dist/index.mjs",
"uiconfig-tweakpane": "https://unpkg.com/uiconfig-tweakpane@latest/dist/index.mjs"
}
}

</script>
<style id="example-style">
html, body, #canvas-container, #mcanvas {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
</style>
<script type="module" src="../examples-utils/simple-code-preview.mjs"></script>
<script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script>
</head>
<body>
<div id="canvas-container">
<canvas id="mcanvas"></canvas>
</div>

</body>

+ 31
- 0
examples/fullscreen-plugin/script.ts Wyświetl plik

@@ -0,0 +1,31 @@
import {_testFinish, FullScreenPlugin, IObject3D, ThreeViewer, TweakpaneUiPlugin} from 'threepipe'
import {createSimpleButtons} from '../examples-utils/simple-bottom-buttons.js'

async function init() {

const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas') as HTMLCanvasElement,
})

const fullScreenPlugin = viewer.addPluginSync(new FullScreenPlugin())

await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr')
await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf')

createSimpleButtons({
['Enter/Exit fullscreen']: () => {
if (fullScreenPlugin.isFullScreen()) fullScreenPlugin.exit()
else fullScreenPlugin.enter(document.body) // parameter is optional, if not specified, the viewer canvas will be used

// or just use
// fullScreenPlugin.toggle(document.body)
},
})


const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true))
ui.setupPluginUi(FullScreenPlugin)

}

init().then(_testFinish)

+ 1
- 0
examples/index.html Wyświetl plik

@@ -234,6 +234,7 @@
<h2 class="category">Interaction</h2>
<ul>
<li><a href="./dropzone-plugin/">Dropzone (Drag & Drop) Plugin </a></li>
<li><a href="./fullscreen-plugin/">FullScreen Plugin </a></li>
</ul>
<h2 class="category">UI Config</h2>
<ul>

+ 1
- 1
package.json Wyświetl plik

@@ -1,6 +1,6 @@
{
"name": "threepipe",
"version": "0.0.7",
"version": "0.0.8-dev",
"description": "A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.",
"main": "src/index.ts",
"module": "dist/index.mjs",

+ 1
- 0
src/plugins/index.ts Wyświetl plik

@@ -13,6 +13,7 @@ export {TweakpaneUiPlugin} from './ui/tweakpane/TweakpaneUiPlugin'

// interaction
export {DropzonePlugin, type DropzonePluginOptions} from './interaction/DropzonePlugin'
export {FullScreenPlugin} from './interaction/FullScreenPlugin'

// import
export {Rhino3dmLoadPlugin} from './import/Rhino3dmLoadPlugin'

+ 106
- 0
src/plugins/interaction/FullScreenPlugin.ts Wyświetl plik

@@ -0,0 +1,106 @@
import {uiButton, uiFolderContainer} from 'uiconfig.js'
import {AViewerPluginSync} from '../../viewer'

/**
* A simple plugin that provides functions to enter, exit, toggle full screen mode and check if the viewer is in full screen mode.
* Implementation from:
* https://stackoverflow.com/questions/50568474/how-to-enter-fullscreen-in-three-js
* @todo: try out some lib like https://github.com/sindresorhus/screenfull for proper cross browser support
*/
@uiFolderContainer('Full Screen')
export class FullScreenPlugin extends AViewerPluginSync<'enter'|'exit'> {
public static readonly PluginType = 'FullScreenPlugin'

toJSON: any = undefined

enabled = true

constructor() {
super()
this.enter = this.enter.bind(this)
this.exit = this.exit.bind(this)
}

private _lastSize = ['100%', '100%']
private _lastFsElement: any = null

private _fsChangeHandler = (_: Event) => {
if (this.isFullScreen()) {
/* Run code when going to fs mode */
this.dispatchEvent({type: 'enter'})

} else {
/* Run code when going back from fs mode */
const elem = this._lastFsElement || this._viewer?.canvas
if (elem) {
elem.style.width = this._lastSize[0]
elem.style.height = this._lastSize[1]
}

document.removeEventListener('webkitfullscreenchange', this._fsChangeHandler, false)
document.removeEventListener('mozfullscreenchange', this._fsChangeHandler, false)
document.removeEventListener('fullscreenchange', this._fsChangeHandler, false)
document.removeEventListener('MSFullscreenChange', this._fsChangeHandler, false)

this.dispatchEvent({type: 'exit'})
}
}

@uiButton('Enter FullScreen')
async enter(element?: HTMLElement): Promise<void> {
if (this.isFullScreen()) return

const elem = element || this._viewer?.canvas as any

if (!elem) return

this._lastFsElement = elem

if (document.addEventListener) {
document.addEventListener('webkitfullscreenchange', this._fsChangeHandler, false)
document.addEventListener('mozfullscreenchange', this._fsChangeHandler, false)
document.addEventListener('fullscreenchange', this._fsChangeHandler, false)
document.addEventListener('MSFullscreenChange', this._fsChangeHandler, false)
}

this._lastSize = [elem.style.width, elem.style.height]
elem.style.width = '100%'
elem.style.height = '100%'

if (elem.requestFullscreen) {
return elem.requestFullscreen()
} else if (elem.mozRequestFullScreen) { /* Firefox */
return elem.mozRequestFullScreen()
} else if (elem.webkitRequestFullscreen) { /* Chrome, Safari & Opera */
return elem.webkitRequestFullscreen()
} else if (elem.msRequestFullscreen) { /* IE/Edge */
return elem.msRequestFullscreen()
}
}
@uiButton('Exit FullScreen')
async exit(): Promise<void> {
if (document.exitFullscreen) {
return document.exitFullscreen()
} else if ((document as any).mozCancelFullScreen) { /* Firefox */
return (document as any).mozCancelFullScreen()
} else if ((document as any).webkitExitFullscreen) { /* Chrome, Safari and Opera */
return (document as any).webkitExitFullscreen()
} else if ((document as any).msExitFullscreen) { /* IE/Edge */
return (document as any).msExitFullscreen()
}
}
@uiButton('Toggle FullScreen')
async toggle(elem: HTMLElement): Promise<void> {
if (this.isFullScreen()) {
return this.exit()
} else {
return this.enter(elem)
}
}

isFullScreen() {
return (document as any).webkitIsFullScreen ||
(document as any).mozFullScreen ||
(document as any).msFullscreenElement !== undefined
}
}

+ 1
- 1
src/plugins/ui/tweakpane/TweakpaneUiPlugin.ts Wyświetl plik

@@ -55,8 +55,8 @@ export class TweakpaneUiPlugin extends UiConfigRendererTweakpane implements IVie
}
this._plugins.push(p)
if (p.uiConfig && p.uiConfig.hidden === undefined) p.uiConfig.hidden = false // todo; this is a hack for now
this.appendChild(p)
const ui = p.uiConfig
this.appendChild(ui)
this._setupPluginSerializationContext(ui, p)
return ui
}

+ 3
- 2
src/viewer/AViewerPlugin.ts Wyświetl plik

@@ -2,17 +2,18 @@ import {ISerializedConfig, ThreeViewer} from './ThreeViewer'
import {Event, EventDispatcher} from 'three'
import {SerializationMetaType, ThreeSerialization} from '../utils'
import {IViewerPlugin, IViewerPluginAsync} from './IViewerPlugin'
import {UiObjectConfig} from 'uiconfig.js'

/**
* Base Class for Viewer Plugins
* @category Viewer
*/
export abstract class AViewerPlugin<T extends string, TViewer extends ThreeViewer = ThreeViewer, IsSync extends boolean = boolean> extends EventDispatcher<Event, T|'serialize'|'deserialize'> implements IViewerPlugin<TViewer, IsSync> {
export abstract class AViewerPlugin<T extends string = string, TViewer extends ThreeViewer = ThreeViewer, IsSync extends boolean = boolean> extends EventDispatcher<Event, T|'serialize'|'deserialize'> implements IViewerPlugin<TViewer, IsSync> {
declare ['constructor']: typeof AViewerPlugin
public static readonly PluginType: string = 'AViewerPlugin'
protected _dirty = false

// uiConfig?: UiObjectConfig = undefined // todo: this should work when uncommented, remove all get uiConfig and do it properly
uiConfig?: UiObjectConfig = undefined // todo: this should work when uncommented, remove all get uiConfig and do it properly

protected _viewer?: TViewer


+ 2
- 2
src/viewer/IViewerPlugin.ts Wyświetl plik

@@ -1,4 +1,4 @@
import {IUiConfigContainer} from 'uiconfig.js'
import {IUiConfigContainer, UiConfigContainer} from 'uiconfig.js'
import {Class, IDisposable, IJSONSerializable} from 'ts-browser-helpers'
import {SerializationMetaType} from '../utils'
import {ISerializedConfig, ThreeViewer} from './ThreeViewer'
@@ -8,7 +8,7 @@ import {ISerializedConfig, ThreeViewer} from './ThreeViewer'
* @category Viewer
*/
export interface IViewerPlugin<TViewer extends ThreeViewer = ThreeViewer, IsSync extends boolean = boolean>
extends IUiConfigContainer, Partial<IJSONSerializable<ISerializedConfig, SerializationMetaType>>, IDisposable {
extends IUiConfigContainer, Partial<IJSONSerializable<ISerializedConfig, SerializationMetaType>>, IDisposable, Partial<UiConfigContainer> {
// all classes must have this static property with a unique identifier value for this plugin
constructor: {
PluginType: string

Ładowanie…
Anuluj
Zapisz