forked from: Picture Book [Alternativa3D 7.6 TIPS]
/**
* Copyright laveklint ( http://wonderfl.net/user/laveklint )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/eijl
*/
// forked from narutohyper's Picture Book [Alternativa3D 7.6 TIPS]
package {
import alternativ7.engine3d.containers.ConflictContainer;
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.View;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.ui.Keyboard;
[SWF(backgroundColor="#000000", frameRate="100", width="465", height="465")]
public class Main extends Sprite {
private const pageMaxNum:uint = 10
private const pageWidth:Number = 640
private const pageHeight:Number = 480
//ページの間隔
//背表紙は手抜きなので、ページ間隔を広くすると、ページ遷移で、背表紙に隙間が発生するので注意
private const pagePitch:Number=1
private var container:ConflictContainer;
private var camera:Camera3D;
private var cameraController:SimpleObjectController;
private var bookController:SimpleObjectController;
private var book:Book
public function Main() {
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.HIGH;
//---------------------------------
// Root objectの作成
//---------------------------------
container = new ConflictContainer();
//---------------------------------
//cameraの作成
//---------------------------------
camera = new Camera3D();
camera.view = new View(465, 465);
addChild(camera.view);
camera.rotationX = -90*Math.PI/180;
camera.rotationZ = -80*Math.PI/180;
camera.x = 0;
camera.y = -500;
camera.z = 0;
container.addChild(camera);
//----------------------------------------------------
// Camera controller
//----------------------------------------------------
cameraController = new SimpleObjectController(stage, camera, 200);
cameraController.mouseSensitivity = 0
cameraController.unbindAll()
//カメラは固定
camera.debug = true;
addChild(camera.diagram);
//----------------------------------------------------
// 読み込み画像リスト
//----------------------------------------------------
var URLList:Vector.<String> = new Vector.<String>(pageMaxNum)
for (var i:uint = 0; i < pageMaxNum; i++) {
URLList[i]='http://marubayashi.net/archive/sample/alt3d7/picturebook/' + String('0' + i).substr( -2, 2) + '.jpg';
}
book = new Book(URLList, pageWidth, pageHeight, pagePitch);
book.rotationX=90*Math.PI/180
book.addEventListener(Event.COMPLETE, onMaterialsLoad)
container.addChild(book);
//----------------------------------------------------
// Camera controller
//----------------------------------------------------
bookController = new BookController(stage, book, 200);
bookController.mouseSensitivity = 0
bookController.unbindAll()
bookController.bindKey(Keyboard.LEFT, SimpleObjectController.ACTION_YAW_LEFT)
bookController.bindKey(Keyboard.RIGHT,SimpleObjectController.ACTION_YAW_RIGHT)
bookController.bindKey(Keyboard.DOWN, SimpleObjectController.ACTION_PITCH_DOWN)
bookController.bindKey(Keyboard.UP,SimpleObjectController.ACTION_PITCH_UP)
//カメラは固定
onResize();
}
private function onMaterialsLoad(e:Event):void {
stage.addEventListener(Event.RESIZE, onResize);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
//stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
public function onResize(e:Event = null):void {
camera.view.width = stage.stageWidth// - pd*2;
camera.view.height = stage.stageHeight// - pd*2;
camera.view.x = 0//pd;
camera.view.y = 0//pd;
}
public function onEnterFrame(e:Event = null):void {
bookController.update();
cameraController.lookAtXYZ(0,0,book.z)
cameraController.update();
camera.render();
}
}
}
//-----------------------------------------------------------------
//_BookController
//-----------------------------------------------------------------
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Object3D;
import flash.display.InteractiveObject;
import flash.events.KeyboardEvent;
import flash.geom.Vector3D;
class BookController extends SimpleObjectController{
public var _target:Object3D
private var _yawSpeed:Number= 1.5
private var _pitchSpeed:Number = 10
public var _pitchDown:Boolean
public var _pitchUp:Boolean
public var _yawLeft:Boolean
public var _yawRight:Boolean
public var _yawNear:Boolean=false
public var _yawNearAngle:Number
public var _pitchNear:Boolean=false
public var _pitchNearAngle:Number
public function BookController(param0:InteractiveObject, param1:Object3D, param2:Number, param3:Number = 3, param4:Number = 1) {
_target=param1
super(param0, param1, param2, param3, param4);
param0.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
param0.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}
public function onKeyDown(e:KeyboardEvent):void {
for (var key:String in keyBindings) {
if (String(e.keyCode)==key) {
keyBindings[key](true)
}
}
}
public function onKeyUp(e:KeyboardEvent = null):void {
for (var key:String in keyBindings) {
keyBindings[key](false)
}
_yawNear = false
_pitchNear = false;
}
override public function bindKey(param0:uint, param1:String): void {
switch (param1) {
case ACTION_YAW_LEFT:
keyBindings[param0]=yawLeft
break
case ACTION_YAW_RIGHT:
keyBindings[param0]=yawRight
break
case ACTION_PITCH_DOWN:
keyBindings[param0]=pitchDown
break
case ACTION_PITCH_UP:
keyBindings[param0]=pitchUp
break
}
super.bindKey(param0, param1)
}
public function pitchDown(value:Boolean):void {
_pitchDown=value
}
public function pitchUp(value:Boolean):void {
_pitchUp=value
}
public function yawLeft(value:Boolean,near:Boolean=false):void {
_yawLeft = value
if (near) {
_yawNear = true
}
}
public function yawRight(value:Boolean,near:Boolean=false):void {
_yawRight = value
if (near) {
_yawNear = true
}
}
override public function update(): void {
if (_yawLeft) {
_target.rotationY = (((_target.rotationY / Math.PI * 180) - _yawSpeed) % 360) * Math.PI/180
} else if (_yawRight) {
_target.rotationY = (((_target.rotationY / Math.PI * 180) + _yawSpeed) % 360) * Math.PI/180
}
if (_pitchDown) {
_target.z = _target.z - _pitchSpeed
}
if (_pitchUp) {
_target.z = _target.z + _pitchSpeed
}
super.update()
updateObjectTransform()
}
public function set yawSpeed(value:Number):void {
_yawSpeed = value*Math.PI/180;
}
public function set pitchSpeed(value:Number):void
{
_pitchSpeed = value
}
}
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.loaders.MaterialLoader;
import alternativ7.engine3d.materials.TextureMaterial;
import flash.events.Event;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.*;
import org.libspark.betweenas3.tweens.ITween;
import org.libspark.betweenas3.tweens.ITweenGroup;
import flash.system.ApplicationDomain
import flash.system.Security;
import flash.system.LoaderContext;
/**
*
* 絵本クラス
* ...
* @author narutohyper
*/
class Book extends Object3DContainer
{
public static const MOVE_END:String='move_end'
private var _pageMaxNum:uint
private var _materialLoader:MaterialLoader
private var _pages:Vector.<PictureBoard>
private var _pagePitch:Number
private var _spine:BookSpine
private var _nowPage:uint = 0
private var context :LoaderContext = new LoaderContext();
public function Book(URLList:Vector.<String>,pageWidth:Number,pageHeight:Number,pagePitch:Number) {
//読み込み終わったMaterialをUVでPlaneに割り付ける
_pageMaxNum = URLList.length
_pagePitch = pagePitch
var materials:Vector.<TextureMaterial> = new Vector.<TextureMaterial>(_pageMaxNum)
_pages=new Vector.<PictureBoard>(_pageMaxNum+1)
var side:String
for (var i:uint = 0; i <= _pageMaxNum;i++) {
if (i == 0) {
side = 'LEFT';
} else if (i==_pageMaxNum) {
side = 'RIGHT';
} else {
side = 'BOTH';
}
_pages[i] = new PictureBoard(i, pageWidth, pageHeight,side,pagePitch*(_pageMaxNum-1));
if (i == _pageMaxNum) {
//最後のページは、裏表紙なので、最初のmaterialを使いまわし
_pages[i].setMaterial(materials[0]);
} else {
//MaterialLoderで読み込む為のMaterialリストを作成
materials[i] = new TextureMaterial();
materials[i].diffuseMapURL = URLList[i]
_pages[i].setMaterial(materials[i]);
}
_pages[i].z = i * -_pagePitch;
addChild(_pages[i]);
}
//画像をMaterialLoaderでまとめて読み込む
Security.loadPolicyFile("http://marubayashi.net/crossdomain.xml");
context.applicationDomain = ApplicationDomain.currentDomain;
_materialLoader = new MaterialLoader();
_materialLoader.addEventListener(Event.COMPLETE, onMaterialsLoad);
_materialLoader.load(materials);
//背表紙の作成
_spine=new BookSpine(_pageMaxNum,_pagePitch, pageHeight,materials[0],pageWidth)
addChild(_spine);
_spine.rotationY=90*Math.PI/180
}
private function onMaterialsLoad(e:Event):void {
//MaterialのLoad処理終了
_materialLoader.removeEventListener(Event.COMPLETE, onMaterialsLoad);
this.dispatchEvent(e);
}
private var _tg:ITweenGroup
private var _nextPage:uint
//--------------------------------------------------
//ページめくり処理
//--------------------------------------------------
public function rightClick(id:uint):void {
if (_nowPage==id) {
_nextPage=id-1
var _t:Array=[]
_t[0] = BetweenAS3.tween(_pages[id].rightPage, {rotationY:-Math.PI}, null, 1)
_t[1] = BetweenAS3.tween(_pages[id - 1].leftPage, { rotationY:0 }, null, 1)
//次のページが一番上に来るように移動
var i:uint
for (i = 0; i <= _pageMaxNum; i++) {
_t.push(BetweenAS3.tween(_pages[i], {z:Math.abs(_nextPage-i)*-_pagePitch}, null, 1))
}
//背表紙の調整
for (i = 0; i < _pageMaxNum; i++) {
if (i>=_nextPage) {
_t.push(BetweenAS3.tween(_spine.spines[i], { x:(Math.abs(_nextPage-i)+1) * _pagePitch }, null, 1))
_t.push(BetweenAS3.tween(_spine.spines[i], { rotationY:0 }, null, 1))
} else {
_t.push(BetweenAS3.tween(_spine.spines[i], { x:(Math.abs(_nextPage-i)-1) * _pagePitch }, null, 1))
}
}
_tg = BetweenAS3.parallelTweens(_t);
_tg.play();
_nowPage=_nextPage
}
}
public function leftClick(id:uint):void {
if (_nowPage==id) {
_nextPage=id+1
var _t:Array=[]
_t[0] = BetweenAS3.tween(_pages[id].leftPage, {rotationY:Math.PI}, null, 1)
_t[1] = BetweenAS3.tween(_pages[id + 1].rightPage, { rotationY:0 }, null, 1)
//次のページが一番上に来るように移動
var i:uint
var t1:ITween
for (i = 0; i <= _pageMaxNum; i++) {
_t.push(BetweenAS3.tween(_pages[i], {z:Math.abs(_nextPage-i)*-_pagePitch}, null, 1))
}
//背表紙の調整
for (i = 0; i < _pageMaxNum; i++) {
if (i<_nextPage) {
_t.push(BetweenAS3.tween(_spine.spines[i], { x:(Math.abs(_nextPage-i)-1) * _pagePitch }, null, 1))
_t.push(BetweenAS3.tween(_spine.spines[i], { rotationY:Math.PI }, null, 1))
} else {
_t.push(BetweenAS3.tween(_spine.spines[i], { x:(Math.abs(_nextPage-i)+1) * _pagePitch }, null, 1))
}
}
_tg = BetweenAS3.parallelTweens(_t);
_tg.play();
_nowPage=_nextPage
}
}
public function moveEnd(e:Event):void {
this.dispatchEvent(new Event(MOVE_END))
}
}
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.core.Vertex;
import alternativ7.engine3d.materials.TextureMaterial;
import alternativ7.engine3d.primitives.Plane;
/**
* 背表紙
* ちょっと手抜き
*
* ...
* @author narutohyper
*/
class BookSpine extends Object3DContainer
{
private var _spines:Vector.<Plane>
public function BookSpine(pageMaxNum:uint,w:Number,h:Number,material:TextureMaterial,maxWidth:Number)
{
_spines = new Vector.<Plane>(pageMaxNum)
var pitch:Number = w / maxWidth
var su:Number=0.5-(pageMaxNum*w)/maxWidth/2
var eu:Number = su + pitch
for (var i:uint = 0; i < pageMaxNum; i++ ) {
_spines[i] = new Plane(w, h, 1, 1, false, false, false,null , material);
addChild(_spines[i]);
_spines[i].x = i * w+w
//中心点を、右端にずらす
_spines[i].faces[0].vertices[0].x -= w /2;
_spines[i].faces[0].vertices[1].x -= w /2;
_spines[i].faces[0].vertices[2].x -= w /2;
_spines[i].faces[0].vertices[3].x -= w / 2;
_spines[i].faces[0].vertices[0].u = su;
_spines[i].faces[0].vertices[0].v = 1;
_spines[i].faces[0].vertices[1].u = eu;
_spines[i].faces[0].vertices[1].v = 1;
_spines[i].faces[0].vertices[2].u = eu;
_spines[i].faces[0].vertices[2].v = 0;
_spines[i].faces[0].vertices[3].u = su;
_spines[i].faces[0].vertices[3].v = 0;
su += pitch
eu += pitch
}
}
public function get spines():Vector.<Plane> {
return _spines;
}
}
import alternativ7.engine3d.core.MouseEvent3D;
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.materials.TextureMaterial;
import alternativ7.engine3d.primitives.Plane;
/**
* ポップアップパーツや絵本ページの元になるクラス
* 一枚のTextureMaterialを2枚のPlaneにUVで割り当てる
* ...
* @author narutohyper
*/
class PictureBoard extends Object3DContainer {
private var _rightPage:Object3DContainer
private var _leftPage:Object3DContainer
private var _rightPlane:Plane
private var _leftPlane:Plane
private var _id:uint;
private var _side:String
private var _pagePitchMax:Number
public function PictureBoard(id:uint, w:Number, h:Number, side:String = null,pagePitchMax:Number=0) {
_id = id;
_side = side;
if (side!='LEFT') {
_rightPlane = new Plane(w / 2, h, 1, 1,false);
_rightPage = new Object3DContainer
_rightPage.addChild(_rightPlane)
_rightPlane.x=w/4
_rightPage.addEventListener(MouseEvent3D.CLICK, onRightClick);
addChild(_rightPage)
_rightPage.rotationY=-180*Math.PI/180
}
if (side!='RIGHT') {
_leftPlane = new Plane(w / 2, h, 1, 1,false);
_leftPage = new Object3DContainer
_leftPage.addChild(_leftPlane);
_leftPlane.x=-w/4
_leftPage.addEventListener(MouseEvent3D.CLICK, onLeftClick);
addChild(_leftPage)
}
trace(pagePitchMax)
_pagePitchMax = pagePitchMax/w/2
}
public function setMaterial(material:TextureMaterial):void {
//UVを直接弄る
var _su:Number=0.5
if (_leftPlane) {
if (_side == 'LEFT') {
//表紙は背表紙分を間引く
_su-=_pagePitchMax
}
_leftPlane.setMaterialToAllFaces(material)
_leftPlane.faces[0].vertices[0].u=0
_leftPlane.faces[0].vertices[0].v=1
_leftPlane.faces[0].vertices[1].u=_su
_leftPlane.faces[0].vertices[1].v=1
_leftPlane.faces[0].vertices[2].u=_su
_leftPlane.faces[0].vertices[2].v=0
_leftPlane.faces[0].vertices[3].u=0
_leftPlane.faces[0].vertices[3].v = 0
}
if (_rightPlane) {
if (_side == 'RIGHT') {
//表紙は背表紙分を間引く
_su+=_pagePitchMax
}
_rightPlane.setMaterialToAllFaces(material)
_rightPlane.faces[0].vertices[0].u=_su
_rightPlane.faces[0].vertices[0].v=1
_rightPlane.faces[0].vertices[1].u=1
_rightPlane.faces[0].vertices[1].v=1
_rightPlane.faces[0].vertices[2].u=1
_rightPlane.faces[0].vertices[2].v=0
_rightPlane.faces[0].vertices[3].u=_su
_rightPlane.faces[0].vertices[3].v=0
}
}
private function onRightClick(e:MouseEvent3D):void {
Book(parent).rightClick(_id)
}
private function onLeftClick(e:MouseEvent3D):void {
Book(parent).leftClick(_id)
}
public function get rightPage():Object3DContainer {
return _rightPage;
}
public function get leftPage():Object3DContainer {
return _leftPage;
}
}