소스 검색

Add FullScreenPlugin and example, other minor fixes.

master
Palash Bansal 2 년 전
부모
커밋
e7d710ade9
No account linked to committer's email address

+ 1
- 1
examples/examples-utils/simple-code-preview.mjs 파일 보기

scripts, scripts,
scripts.map(s=>s.textContent ? 'js' : s.split('.').pop()), // title 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 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, title: 'ThreePipe: ' + document.title,
css, css,

+ 35
- 0
examples/fullscreen-plugin/index.html 파일 보기

<!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 파일 보기

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 파일 보기

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

+ 1
- 1
package.json 파일 보기

{ {
"name": "threepipe", "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.", "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", "main": "src/index.ts",
"module": "dist/index.mjs", "module": "dist/index.mjs",

+ 1
- 0
src/plugins/index.ts 파일 보기



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


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

+ 106
- 0
src/plugins/interaction/FullScreenPlugin.ts 파일 보기

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 파일 보기

} }
this._plugins.push(p) this._plugins.push(p)
if (p.uiConfig && p.uiConfig.hidden === undefined) p.uiConfig.hidden = false // todo; this is a hack for now 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 const ui = p.uiConfig
this.appendChild(ui)
this._setupPluginSerializationContext(ui, p) this._setupPluginSerializationContext(ui, p)
return ui return ui
} }

+ 3
- 2
src/viewer/AViewerPlugin.ts 파일 보기

import {Event, EventDispatcher} from 'three' import {Event, EventDispatcher} from 'three'
import {SerializationMetaType, ThreeSerialization} from '../utils' import {SerializationMetaType, ThreeSerialization} from '../utils'
import {IViewerPlugin, IViewerPluginAsync} from './IViewerPlugin' import {IViewerPlugin, IViewerPluginAsync} from './IViewerPlugin'
import {UiObjectConfig} from 'uiconfig.js'


/** /**
* Base Class for Viewer Plugins * Base Class for Viewer Plugins
* @category Viewer * @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 declare ['constructor']: typeof AViewerPlugin
public static readonly PluginType: string = 'AViewerPlugin' public static readonly PluginType: string = 'AViewerPlugin'
protected _dirty = false 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 protected _viewer?: TViewer



+ 2
- 2
src/viewer/IViewerPlugin.ts 파일 보기

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

Loading…
취소
저장