So basically, I am making a robot object in javascript using Three.js and am passing in the three.js scene variable object I am using to draw the robot parts through the array- for some reason, though, the scene object will not pass into the function (it won't draw)- Am I missing something about javascript functions?
function Robot(sc){
this.sc=sc;
var robtexture = new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('tex/dmetal.png')
});
this.parts = [];
var current;
//make body
current=new THREE.Mesh(new THREE.CubeGeometry(10,15,10), robtexture);
this.parts.push(current);
alert("hit");
//make legs
}
Robot.prototype.draw = function() {
for (x in this.parts){
this.sc.add(x);
alert("hit");
}
}
Maybe this works more like you intended:
Robot.prototype.draw = function() {
for (x in this.parts){
this.sc.add(this.parts[x]); // < - spot the difference :)
alert("hit");
}
}
Related
I have the below AS3 code, and I want to translate it to Haxe. But I don't know how to deal with the keyword prototype. Who can help me? Thanks.
var style = new CSSStyleDeclaration();
style.defaultFactory = function():void
{
this.disabledOverlayAlpha = 0;
this.borderStyle = "controlBar";
this.paddingTop = 10;
this.verticalAlign = "middle";
this.paddingLeft = 10;
this.paddingBottom = 10;
this.paddingRight = 10;
};
if(chain == null) chain = {};
style.defaultFactory.prototype = chain;
chain = new style.defaultFactory();
style.defaultFactory = function():void
{
this.fontWeight = "bold";
};
style.defaultFactory.prototype = chain;
chain = new style.defaultFactory();
style.defaultFactory = function():void
{
this.backgroundSize = "100%";
this.paddingTop = 24;
this.backgroundColor = 8821927;
this.backgroundImage = ApplicationBackground;
this.horizontalAlign = "center";
this.backgroundGradientAlphas = [1,1];
this.paddingLeft = 24;
this.paddingBottom = 24;
this.paddingRight = 24;
};
style.defaultFactory.prototype = chain;
chain = new style.defaultFactory();
Ok, I poked this a bit, and now I kind of figured out, what that piece of code does. This knowledge won't help you to port your code to HAXE, but it will help you understand what it is about and to compose a decent HAXE-style alternative.
First, the part about instantiating, functions and working with prototypes. As it turned out, if you invoke the new operator on an unbound function (does not work on class methods):
The new empty class-less generic Object is created.
Its reference is passed to the said function as this.
The function can add and modify the object's fields and methods.
Ultimately, the reference to that Object is returned.
Then, it works (as I mentioned in my comments above) very much the way classes worked back then in AS1 and Flash 6.
If that function has a prototype and it is too a generic Object, then it is added to the newly created one as a... how to put it... a bottom layer Object which adds its fields to the top layer Object.
I understand that it sounds difficult, so there's an explanatory example that somehow sheds some light on it all:
public class Proton extends Sprite
{
public function Proton()
{
super();
var P:Function;
// Empty.
P = new Function;
create("First:", P);
// Empty with prototype.
P.prototype = {c:3, d:4};
create("Second:", P);
// Non-empty.
P = function():void
{
this.a = 1;
this.b = 2;
};
create("Third:", P);
// Non-empty with prototype.
P.prototype = {a:5, f:6};
create("Fourth:", P);
}
// Instantiates the F and outputs the result.
private function create(prefix:String, F:Function):void
{
var A:Object = new F;
trace(prefix + "\nJSON:" + JSON.stringify(A) + "\nREAL:" + explore(A) + "\n");
}
// Same as JSON.stringify, but also looks into the prototype.
private function explore(O:Object):String
{
var result:Array = new Array;
for (var akey:String in O)
{
result.push('"' + akey + '":' + O[akey]);
}
return "{" + result.join(",") + "}";
}
}
So, the output is:
First:
JSON:{}
REAL:{}
Second:
JSON:{}
REAL:{"d":4,"c":3}
Third:
JSON:{"b":2,"a":1}
REAL:{"b":2,"a":1}
Fourth:
JSON:{"b":2,"a":1}
REAL:{"b":2,"a":1,"f":6,"a":1}
As you can see, JSON.stringify exports only the top layer object, while direct for iteration goes through all the layers, top to bottom, and even processes the duplicate keys (but the top layer value shadows what's below).
Second, how it all is related to your code. These factory and defaultFactory functions are used in some CSS-related class to form an Object representation of the style: https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/styles/CSSStyleDeclaration.html
So, you can use that prototype hack to form a generic Object with a chain of layers upon layers of CSS declarations... probably. You saw that JSON doesn't perceive anything but the top layer, I have no idea if CSS classes act differently or not.
I think, working with CSS should be less hack-y and more straightforward.
Good luck figuring it out.
I been searching for a way to handle this for hours but have found nothing. In my BuildMap function, I instantiate new MovieClips (Tile) with the instance name cell. Their frame is based on my 2d array (protoMap). The problem is that the cells are instantiated in the function. I don't know how to access them outside of it. I want to removeChild(cell) but the only way I know how is within the function that it's instantiated in.
public function BuildMap()
{
for (var i:int=0; i < mapHeight; i++)
{
for (var u:int=0; u < mapWidth; u++)
{
var cell:MovieClip = new Tile();
cell.gotoAndStop(protoMap[i][u]+1);
cell.x = tileSide*u;
cell.y = tileSide*i;
addChild(cell);
var currCellLabel:String = cell.currentFrameLabel;
mapLabels[i].push(currCellLabel);
}
}
}
I want a function called ClearMap() that loops through again and does removeChild(cell). I thought about doing a clearTiles:Boolean and in BuildMap() do
if(clearTiles == false)
{
build the map;
}else{loop again and removeChild(cell)}
but that didn't work... so then I tried to pass cell as an argument to BuildMap() but when I tried to remove it, it wasn't an object of the caller... or something like that. I was also thinking to put cell into its own array, but I don't want to waste memory unnecessarily. Any solutions for the noob?
Create a class instead of using functions.
The point of a class is to isolate concerns.
In your case, you want to deal with all those tiles. (create them according to protoMap and be able to delete them all.
Extending a DisplayObjectContainer such as Sprite, will allow you to add all the tiles to the map object, then you can add and remove the map easily.
Your BuildMap function becomes the constructor.
Here's some non working pseudo code that illustrates the idea:
package
{
public class Map extends Sprite
{
public function Map (data, width, height)
{
for (var i:int=0; i < height; i++)
{
for (var u:int=0; u < width; u++)
{
var cell:MovieClip = new Tile();
cell.gotoAndStop(data[i][u]+1);
cell.x = tileSide*u;
cell.y = tileSide*i;
addChild(cell);
var currCellLabel:String = cell.currentFrameLabel;
mapLabels[i].push(currCellLabel);
}
}
}
public function clear():void
{
removeChildren();
}
}
}
The whole map is contained in that class. You'd have to add the labels, but you didn't specify what they are or what they do, so I left them out.
You can use it like so:
var awesomeMap:Map = new Map(protoMap, mapWidth, mapHeight);
addChild(awesomeMap);
//later
awesomeMap.clear();
//or
removeChild(awesomeMap);
I'd like to point out that building tile maps with MovieClips this way is a bad idea. MovieClips are horrible for performance, because they carry the overhead of their timeline.
Removing all children is very wasteful, too.
So if you have performance problems, try reusing objects and/or employing a technique called "blitting"
See this article: http://www.adobe.com/devnet/flash/articles/blitting_mc.html
I have a 3D object of a chair made in Blender and exported as a .obj and .mtl. First of all, the load time is a horrendous 40+ seconds; I have no idea why (Visual Studio possibly?) Second, the images textures are not loading properly. With no ambient or directional lighting I get a silhouette. With the lighting I get a slight hint of gray to give a little depth but nothing close to the many colors in the original object. I have only been working with ThreeJS for a few days now so I'm quite new to it. Hence, I am at a loss. I have read several artciles related to my issue but none seem to solve the problem. I even went so far as to add an addon to Blender to export to .js. I could not get it to even load properly (I assume it had to do with the fact I kept the same loader info from the .OBJMTLLoader and the .JSONLoader doesn't support or needs more than what I gave; I just am not familiar enough with it know). Any ideas/suggestions? Here is my script:
`
<script src="js/three.min.js"></script>
<script src="js/controls/TrackballControls.js"></script>
<script src="js/loaders/MTLLoader.js"></script>
<script src="js/loaders/OBJMTLLoader.js"></script>
<script src="js/Detector.js"></script>
<script>
if (!Detector.webgl) Detector.addGetWebGLMessage();
var container;
var camera, controls, scene, renderer;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 0.01, 1e10);
camera.position.z = 2;
//controls
controls = new THREE.TrackballControls(camera);
controls.rotateSpeed = 5.0;
controls.zoomSpeed = 5;
controls.panSpeed = 2;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
scene = new THREE.Scene();
scene.add(camera);
//lights
var ambient = new THREE.AmbientLight(0xCCCCCC);
scene.add(ambient);
var directionalLight = new THREE.DirectionalLight(0xCCCCCC);
directionalLight.position.set(0, 0, 2).normalize();
scene.add(directionalLight);
//main img
var material = new THREE.MeshBasicMaterial({ color: '0xCCCCCC' });
var loader = new THREE.OBJMTLLoader();
loader.addEventListener('load', function (event) {
var geometry = event.content;
//var mesh = new THREE.Mesh(geometry);
scene.add(geometry, material);
});
loader.load('chair.obj', 'chair.mtl');
// renderer
renderer = new THREE.WebGLRenderer({ antialias: false });
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
//
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
controls.handleResize();
}
function animate() {
requestAnimationFrame(animate);
render();
controls.update();
}
function render() {
var timer = Date.now() * 0.0005;
renderer.render(scene, camera);
}
</script>
`
Well, you are defining a gray MeshBasicMaterial to use with your obj instead of using the material(s) that the loader will create for you, i guess.
Just use this. The "object" should have the material defined in your mtl-file.
loader.addEventListener( 'load', function ( event ) {
var object = event.content;
scene.add( object );
});
loader.load( 'chair.obj', 'chair.mtl' );
Concerning your load time: Could be your local server. Also, be aware that the obj file format ist quite big in raw ascii format. Also, if the mtl-file defines textures, they are maybe quite big in file size, too.
#GuyGood was correct in my case for the long load time. I was using the python simplehttpserver and switch to a node server and no more slow texture loading problems. Check out the threejs wiki for other local server options.
I'm iterating over the component.nonInheritingStyles (UIComponent) and I'm finding duplicate properties. How is that possible?
var array:Array = getArrayFromObject(myLabelComponent.nonInheritingStyles);
/**
*
**/
protected function getArrayFromObject(value:Object):Array {
var array:Array = [];
for (var styleProp:String in value) {
trace("style:"+styleProp); // fontFamily duplicates a few times
array.push({name:styleProp, value:value[styleProp]});
}
return array;
}
All magic in CSSStyleDeclaration class from Flex SDK.
You can find method:
mx_internal function addDefaultStyleToProtoChain(chain:Object,
target:DisplayObject,
filterMap:Object = null):Object
And you can see code:
defaultFactory.prototype = chain;
chain = new defaultFactory();
This is code contain all magic.
For understand it you can write example:
protected function getArrayFromObject(value:Object):Array {
var array:Array = [];
var parentStyleFactory:Function = function():void {
this.x = 1;
}
var styleFactory:Function = function():void {
this.x = 2;
}
var parentStyle:Object = new parentStyleFactory();
styleFactory.prototype = parentStyle;
var style:Object = new styleFactory();
for (var styleProp:String in style) {
trace("style:"+styleProp); // fontFamily duplicates a few times
array.push({name:styleProp, value:style[styleProp]});
}
return array;
}
This is example will trace:
[trace] style:x
[trace] style:x
If you write this example:
var obj:Object = {x:1, y:1};
var factory:Function = function(){
this.x = 2;
};
factory.prototype = obj;
var obj2:Object = new factory();
trace(obj2.x);
trace(obj2.y);
You will see in console:
[trace] 2
[trace] 1
So, if you try to get value for some property flash try to access to object property, if property is absent, it try to access property from prototype.
But when you iterate in forin by object properties flash return you all object properties and all object prototype properties.
My guess would be is that it is grabbing the styles from the inheritance chain one class at a time and not looking for repeating styles. It just doesn't seem to be the purposes of the function.
The beginning of this component's chain of non-inheriting styles. The
getStyle() method simply accesses nonInheritingStyles[styleName] to
search the entire prototype-linked chain. This object is set up by
initProtoChain(). Developers typically never need to access this
property directly.
SOURCE
Maybe you want inheritingStyles
I draw with a mouse Paper.js. I need to keep these strokes and replay them at the same rate as in the video replay. How can I accomplish this?
In paper.js, the onFrame() function is called up to 60 times per second, while the onMouseMove() function "is called when the mouse moves within the project view", and contains the position of the mouse. By using both functions you can store the mouse motions and replay them later with close to the same time between positions.
var mousePosition = null;
function onMouseMove(event) {
if (mousePosition != null) {
var path = new Path();
path.strokeColor = 'black';
path.moveTo(mousePosition);
path.lineTo(event.point);
}
mousePosition = event.point;
}
var recordedPositions = [];
var delayFrames = 60;
function onFrame(event) {
if (mousePosition != null) {
recordedPositions.push(mousePosition);
if (recordedPositions.length > delayFrames) {
var path = new Path();
path.strokeColor = 'red';
delayedPositionIndex = recordedPositions.length - delayFrames;
path.moveTo(recordedPositions[delayedPositionIndex - 1]);
path.lineTo(recordedPositions[delayedPositionIndex]);
}
}
}
I do not know the timing accuracy/resolution/dependability of onFrame(). Alternatively you could just use javascript timing events as in this answer: How can I use javascript timing to control on mouse stop and on mouse move events