界面效果
思路
bootstrap控制界面效果 jquery动态修改界面内容 [Add]增加一个box [Play]导出play.html
,打开play.html
就可以看到程序运行效果
编辑器代码
<! DOCTYPE html >
< html>
< head>
< meta charset = " utf-8" >
< title> 编辑器</ title>
< meta name = " viewport" content = " width=device-width, initial-scale=1.0" >
< link rel = " stylesheet" href = " https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" >
< script src = " https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js" > </ script>
< script src = " https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js" > </ script>
< style>
body {
margin : 0;
width : 100%;
height : 100%;
}
#project {
position : absolute;
z-index : 100;
}
#propertyList {
position : absolute;
z-index : 100;
left : 80%;
right : 0px;
top : 25%;
}
#canvas {
position : absolute;
top : 0px;
left : 0px;
width : 100%;
height : 100%;
z-index : 0;
background : transparent;
touch-action : none;
object-fit : cover;
}
</ style>
</ head>
< body οnresize = " resize_canvas()" >
< div class = " panel panel-default" id = " project" >
< button type = " button" class = " btn btn-default" onclick = " addBox ( ) " > Add</ button>
< button type = " button" class = " btn btn-default" onclick = " startSimulate ( ) " > Play</ button>
< br />
project
< div class = " panel-body" >
< ul class = " list-group" id = " projectUl" >
</ ul>
</ div>
</ div>
< div class = " panel panel-default" id = " propertyList" >
property
< div class = " panel-body" id = " propertyListBody" >
</ div>
</ div>
< canvas id = " canvas" > </ canvas>
< script type = " importmap" >
{
"imports" : {
"@orillusion/core" : "https://unpkg.com/@orillusion/core/dist/orillusion.es.js" ,
"@orillusion/stats" : "https://unpkg.com/@orillusion/stats/dist/stats.es.js" ,
"dat.gui" : "https://npm.elemecdn.com/dat.gui@0.7.9/build/dat.gui.module.js"
}
}
</ script>
< script type = " module" >
import { Engine3D, Scene3D, Object3D, Camera3D, ComponentBase, LitMaterial, BoxGeometry, MeshRenderer, DirectLight, PlaneGeometry, HoverCameraController, View3D, AtmosphericComponent } from '@orillusion/core'
import { Stats } from '@orillusion/stats'
import * as dat from 'dat.gui'
window. startGame = startGame
window. continueGame = continueGame
window. endGame = endGame
window. showMenu = showMenu
window. hideMenu = hideMenu
window. resize_canvas = resize_canvas
window. initGame = initGame
window. selectItem = selectItem
window. startSimulate = startSimulate
window. serializeGame = serializeGame
window. saveFile = saveFile
window. scene2Json = scene2Json
window. addBox = addBox
window. addCamera = addCamera
window. addLight = addLight
let gameState = 'none'
let GUIHelp
let gItemes = new Array ( )
let scene3D
let gCurrentItemIndex = - 1
let gItemsSize = 0
let dataMap = [ ]
function startGame ( ) {
console. log ( "StartGame" )
if ( gameState == 'pause' ) {
continueGame ( )
return
}
hideMenu ( )
gameState = 'start'
initGame ( )
}
function continueGame ( ) {
console. log ( "ContinueGame" )
hideMenu ( )
if ( gameState == 'none' ) {
startGame ( )
}
}
function endGame ( ) {
console. log ( "EndGame" )
}
function showMenu ( ) {
console. log ( "showMenu" )
if ( gameState == 'start' ) {
gameState = 'pause'
Engine3D. pause ( )
}
}
function hideMenu ( ) {
console. log ( "hideMenu" )
let canvas = document. getElementById ( 'canvas' )
if ( gameState == 'pause' ) {
gameState = 'start'
Engine3D. resume ( )
}
}
function resize_canvas ( ) {
canvas = document. getElementById ( "canvas" ) ;
if ( canvas. width < window. innerWidth) {
canvas. width = window. innerWidth;
}
if ( canvas. height < window. innerHeight) {
canvas. height = window. innerHeight;
}
}
async function initGame ( ) {
await Engine3D. init ( {
canvasConfig : { canvas }
} )
scene3D = new Scene3D ( )
addSky ( )
let camera = addCamera ( )
addLight ( )
let view = new View3D ( )
view. scene = scene3D
view. camera = camera
Engine3D. startRenderView ( view)
const GUIHelp = new dat. GUI ( )
GUIHelp. addFolder ( 'Setting' )
GUIHelp. add ( { menu : ( ) => showMenu ( ) } , 'menu' )
}
function addSky ( ) {
let sky = scene3D. addComponent ( AtmosphericComponent)
sky. sunY = 0.6
scene3D. name = 'scene3D'
gCurrentItemIndex = gItemes. length
$ ( "#projectUl" ) . append ( "<li class=\"list-group-item\"> <button type=\"button\" class=\"btn btn-default\" οnclick=\"selectItem(" + gCurrentItemIndex + ")\">" + "scene3D" + "</button> </li>" )
gItemes. push ( {
"obj" : scene3D,
"type" : 'scene3D' ,
"scriptContent" : "" ,
"scriptClassName" : "" ,
} )
return sky
}
function addBox ( ) {
gCurrentItemIndex = gItemes. length
let name = 'box-' + gCurrentItemIndex
$ ( "#projectUl" ) . append ( "<li class=\"list-group-item\"> <button type=\"button\" class=\"btn btn-default\" οnclick=\"selectItem(" + gCurrentItemIndex + ")\">" + name + "</button> </li>" )
const obj = new Object3D ( )
obj. name = name
let mr = obj. addComponent ( MeshRenderer)
mr. geometry = new BoxGeometry ( 5 , 5 , 5 )
mr. material = new LitMaterial ( )
scene3D. addChild ( obj)
gItemes. push ( {
"obj" : obj,
"type" : 'box' ,
"scriptContent" : "" ,
"scriptClassName" : "" ,
} )
}
function addCamera ( ) {
let cameraObj = new Object3D ( )
cameraObj. name = "camera"
let camera = cameraObj. addComponent ( Camera3D)
camera. perspective ( 60 , Engine3D. aspect, 1 , 5000.0 )
let controller = cameraObj. addComponent ( HoverCameraController)
controller. setCamera ( 0 , 0 , 15 )
scene3D. addChild ( cameraObj)
gCurrentItemIndex = gItemes. length
$ ( "#projectUl" ) . append ( "<li class=\"list-group-item\"> <button type=\"button\" class=\"btn btn-default\" οnclick=\"selectItem(" + gCurrentItemIndex + ")\">" + "camera" + "</button> </li>" )
gItemes. push ( {
"obj" : cameraObj,
"type" : 'camera' ,
"scriptContent" : "" ,
"scriptClassName" : "" ,
} )
return camera
}
function addLight ( ) {
let light = new Object3D ( )
light. name = "light"
let component = light. addComponent ( DirectLight)
light. rotationX = 45
light. rotationY = 30
component. intensity = 1
scene3D. addChild ( light)
gCurrentItemIndex = gItemes. length
$ ( "#projectUl" ) . append ( "<li class=\"list-group-item\"> <button type=\"button\" class=\"btn btn-default\" οnclick=\"selectItem(" + gCurrentItemIndex + ")\">" + "light" + "</button> </li>" )
gItemes. push ( {
"obj" : light,
"type" : 'light' ,
"scriptContent" : "" ,
"scriptClassName" : "" ,
} )
return light
}
function selectItem ( index ) {
console. log ( "selectItemIndex: " + index)
gCurrentItemIndex = index
showItemProrperty ( gItemes[ index] )
}
function showItemProrperty ( item ) {
let name = item[ 'obj' ] . name
console. log ( "showItemProrperty: " + item)
$ ( "#propertyListBody" ) . empty ( )
let obj = item[ 'obj' ]
if ( ! obj) {
console. warn ( "scene3D not find: " + name)
return
}
$ ( "#propertyListBody" ) . append ( "<div class=\"input-group\"> <span class=\"input-group-addon\">name</span><input type=\"text\" id=\"objName\" value=" + obj. name + "></input></div><br/>" )
let trans = obj. transform
$ ( "#propertyListBody" ) . append ( "<p>transform</p>" )
$ ( "#propertyListBody" ) . append ( "<p>position</p>" )
$ ( "#propertyListBody" ) . append ( "<div class=\"input-group\"> <span class=\"input-group-addon\">x</span><input type=\"text\" id=\"transX\" value=" + trans. x + "></input></div>" )
$ ( "#propertyListBody" ) . append ( "<div class=\"input-group\"> <span class=\"input-group-addon\">y</span><input type=\"text\" id=\"transY\" value=" + trans. y + "></input></div>" )
$ ( "#propertyListBody" ) . append ( "<div class=\"input-group\"> <span class=\"input-group-addon\">z</span><input type=\"text\" id=\"transZ\" value=" + trans. z + "></input></div>" )
$ ( "#transX" ) . change ( function ( ) { obj. x = $ ( "#transX" ) . val ( ) } )
$ ( "#transY" ) . change ( function ( ) { obj. y = $ ( "#transY" ) . val ( ) } )
$ ( "#transZ" ) . change ( function ( ) { obj. z = $ ( "#transZ" ) . val ( ) } )
$ ( "#propertyListBody" ) . append ( "<p>script</p>" )
$ ( "#propertyListBody" ) . append ( "<textarea class=\"form-control\" rows=\"6\" id=\"textareaScript\">" + item. scriptContent + "</textarea>" )
$ ( "#textareaScript" ) . change ( function ( ) {
let str = $ ( "#textareaScript" ) . val ( )
let className = str. split ( / \s* extends / ) [ 0 ] . replace ( 'class' , '' )
console. log ( "className = " + className + ";gCurrentItemIndex=" + gCurrentItemIndex + ";str=" + str)
if ( gCurrentItemIndex > - 1 ) {
gItemes[ gCurrentItemIndex] . scriptContent = str
gItemes[ gCurrentItemIndex] . scriptClassName = className. trim ( )
}
} )
}
function startSimulate ( ) {
serializeGame ( )
}
function serializeGame ( ) {
saveFile ( 'play.html' )
}
async function getFile ( ) {
const [ fileHandle] = await window. showOpenFilePicker ( ) ;
const file = await fileHandle. getFile ( ) ;
return file;
}
async function saveFile ( path ) {
const newHandle = await window. showSaveFilePicker ( ) ;
const writableStream = await newHandle. createWritable ( ) ;
dataMap = [ ]
let data = scene2Json ( )
console. log ( "scene2Json=" + data)
await writableStream. write ( "<!DOCTYPE html>" ) ;
await writableStream. write ( "<html>" ) ;
await writableStream. write ( "<head>\n" ) ;
await writableStream. write ( "<meta charset=\"utf-8\">\n" ) ;
await writableStream. write ( "<title>Play</title>\n" ) ;
await writableStream. write ( "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" ) ;
await writableStream. write ( "<link rel=\"stylesheet\" href=\"https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css\">\n" ) ;
await writableStream. write ( "<script src=\"https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js\"><\/script>\n" ) ;
await writableStream. write ( "<script src=\"https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js\"><\/script>\n" ) ;
await writableStream. write ( "<style>body {margin: 0;width: 100%;height: 100%;}\n" ) ;
await writableStream. write ( "#canvas {position: absolute;top: 0px;left: 0px;width: 100%;height: 100%;z-index: 0;background: transparent;touch-action: none;object-fit: cover;}\n" ) ;
await writableStream. write ( "</style>\n" ) ;
await writableStream. write ( "</head>\n" ) ;
await writableStream. write ( "<body οnresize=\"resize_canvas()\">\n" ) ;
await writableStream. write ( "<canvas id=\"canvas\"></canvas>\n" ) ;
await writableStream. write ( "<script type=\"importmap\">{\n" ) ;
await writableStream. write ( " \"imports\": {\n" ) ;
await writableStream. write ( "\"@orillusion/core\": \"https://unpkg.com/@orillusion/core/dist/orillusion.es.js\",\n" ) ;
await writableStream. write ( "\"@orillusion/stats\": \"https://unpkg.com/@orillusion/stats/dist/stats.es.js\",\n" ) ;
await writableStream. write ( "\"dat.gui\": \"https://npm.elemecdn.com/dat.gui@0.7.9/build/dat.gui.module.js\"}}\n" ) ;
await writableStream. write ( "<\/script>\n" ) ;
await writableStream. write ( "<script type=\"module\">\n" ) ;
await writableStream. write ( "import { Engine3D, Scene3D, Object3D, Camera3D, ComponentBase, LitMaterial, BoxGeometry, MeshRenderer, DirectLight, PlaneGeometry, HoverCameraController, View3D, AtmosphericComponent } from '@orillusion/core'\n" ) ;
await writableStream. write ( "import { Stats } from '@orillusion/stats'\n" ) ;
await writableStream. write ( "import * as dat from 'dat.gui'\n" ) ;
await writableStream. write ( "import * as localSprite from './localScript.mjs'\n" ) ;
for ( var s = 0 ; s < dataMap. length; s++ ) {
let strScript = dataMap[ s] . scriptContent
if ( strScript == "" ) continue ;
await writableStream. write ( strScript) ;
await writableStream. write ( "\n" ) ;
}
await writableStream. write ( "async function initGame() {\n" ) ;
await writableStream. write ( "await Engine3D.init({ canvasConfig: { canvas } })\n" ) ;
await writableStream. write ( "let scene3D = new Scene3D()\n" ) ;
await writableStream. write ( "let view = new View3D()\n" ) ;
await writableStream. write ( "view.scene = scene3D\n" ) ;
await writableStream. write ( "localSprite.testlocalScript()\n" ) ;
await writableStream. write ( "localSprite.loadObj(scene3D, view, " + data + ")\n" ) ;
for ( var s = 0 ; s < dataMap. length; s++ ) {
if ( dataMap[ s] . scriptClassName != "" ) {
await writableStream. write ( "{ let obj = scene3D.getObjectByName(\"" + dataMap[ s] . name + "\"); " ) ;
await writableStream. write ( "obj.addComponent(" + dataMap[ s] . scriptClassName + ") }\n" ) ;
}
}
await writableStream. write ( "Engine3D.startRenderView(view) }\n" ) ;
await writableStream. write ( "initGame()\n" ) ;
await writableStream. write ( "<\/script>\n" ) ;
await writableStream. write ( "</body>\n" ) ;
await writableStream. write ( "</html>" ) ;
await writableStream. close ( ) ;
}
function scene2Json ( ) {
for ( var i = 0 ; i < gItemes. length; i++ ) {
let item = gItemes[ i]
console. log ( item. obj. name)
let mapobj = {
name : item. obj. name,
type : item. type,
scriptContent : item. scriptContent,
scriptClassName : item. scriptClassName,
x : item. obj. x,
y : item. obj. y,
z : item. obj. z,
scaleX : item. obj. scaleX,
scaleY : item. obj. scaleY,
scaleZ : item. obj. scaleZ,
rotationX : item. obj. rotationX,
rotationY : item. obj. rotationY,
rotationZ : item. obj. rotationZ,
}
let mr = item. obj. getComponent ( MeshRenderer)
if ( mr) {
mapobj. MeshRenderer = { }
let geometry = mr. geometry
if ( geometry) {
mapobj. MeshRenderer. geometry = { }
if ( geometry. constructor === BoxGeometry) {
console. log ( "===========BoxGeometry======================" )
mapobj. MeshRenderer. geometry. type = 'BoxGeometry'
mapobj. MeshRenderer. geometry. width = geometry. width
mapobj. MeshRenderer. geometry. height = geometry. height
mapobj. MeshRenderer. geometry. depth = geometry. depth
}
}
}
dataMap. push ( mapobj)
}
return JSON . stringify ( dataMap)
}
startGame ( )
</ script>
</ body>
</ html>
play.html
是编辑器自动生成的不用修改
localScript.mjs
是方便play.html
动态创建加载Object3D
export function testlocalScript ( ) {
console. log ( "testlocalScript~~~~~~~~~~~~~" )
}
import { Engine3D, Scene3D, Object3D, Camera3D, LitMaterial, BoxGeometry, MeshRenderer, DirectLight, PlaneGeometry, HoverCameraController, View3D, AtmosphericComponent } from "https://unpkg.com/@orillusion/core/dist/orillusion.es.js"
export function loadObj ( scene3D, view, content ) {
console. log ( "loadObj~~~~~~~~~~~~~" + content)
for ( var i = 0 ; i < content. length; i++ ) {
let item = content[ i]
console. log ( "loadObj~~~~~~~~~~~~~" + i + item)
if ( item. type == "scene3D" ) {
addSky ( item, scene3D)
}
else if ( item. type == "light" ) {
addLight ( item, scene3D)
}
else if ( item. type == "camera" ) {
let camera = addCamera ( item, scene3D)
view. camera = camera
}
else if ( item. type == "box" ) {
addBox ( item, scene3D)
}
}
}
function addBox ( item, scene3D ) {
const obj = new Object3D ( )
obj. name = item. name
let mr = obj. addComponent ( MeshRenderer)
if ( item. MeshRenderer) {
if ( item. MeshRenderer. geometry) {
mr. geometry = new BoxGeometry ( item. MeshRenderer. geometry. width,
item. MeshRenderer. geometry. height,
item. MeshRenderer. geometry. depth)
}
}
mr. material = new LitMaterial ( )
setObjInfo ( item, obj)
scene3D. addChild ( obj)
}
function addCamera ( item, scene3D ) {
let cameraObj = new Object3D ( )
cameraObj. name = item. name
let camera = cameraObj. addComponent ( Camera3D)
camera. perspective ( 60 , Engine3D. aspect, 1 , 5000.0 )
let controller = cameraObj. addComponent ( HoverCameraController)
controller. setCamera ( 0 , 0 , 15 )
scene3D. addChild ( cameraObj)
return camera
}
function addLight ( item, scene3D ) {
let light = new Object3D ( )
light. name = item. name
let component = light. addComponent ( DirectLight)
light. rotationX = 45
light. rotationY = 30
component. intensity = 1
scene3D. addChild ( light)
return light
}
function addSky ( item, scene3D ) {
let sky = scene3D. addComponent ( AtmosphericComponent)
sky. sunY = 0.6
return sky
}
function setObjInfo ( item, obj ) {
obj. x = item. x
obj. y = item. y
obj. z = item. z
obj. rotationX = item. rotationX
obj. rotationY = item. rotationY
obj. rotationZ = item. rotationZ
}
物体的脚本也会动态写入play.html
,所以支持物体脚本行为
play效果