HaxeFlixel animations not playing - animation

I'm trying to make a simple little game in HaxeFlixel, where you play as a ghost and you go around an apartment complex knocking on doors. There's a bit more to it than that, but that's the fundamental idea. Anyway, I've currently got the ghost moving from door to door, and knocking on them, but for some reason the animation where the tenant opens the door isn't triggering.
Here is the state:
package;
import flixel.addons.display.FlxBackdrop;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.FlxG;
import flixel.group.FlxTypedGroup;
import flixel.group.FlxTypedGroupIterator;
import flixel.text.FlxText;
import flixel.util.FlxPoint;
/**
* ...
* #author ...
*/
class GhostState extends FlxState
{
var ghost:FlxSprite;
var hall:FlxBackdrop;
var wall:FlxSprite;
var knock :Array<FlxText>;
public var doors:FlxTypedGroup<Door>;
public var speed = 0;
public var inTransit:Bool;
public var knockCount = 0;
public var doneWithThisDoor = false;
public var doorIndex = 0;
public function justPressed():Bool
{
#if mobile
var returnVal = false;
for (touch in FlxG.touches.list)
{
returnVal = touch.justPressed;
}
return returnVal;
#else
return FlxG.mouse.justPressed;
#end
}
public function pressed():Bool
{
#if mobile
var returnVal = false;
for (touch in FlxG.touches.list)
{
returnVal = touch.pressed;
}
return returnVal;
#else
return FlxG.mouse.pressed;
#end
}
public function justReleased():Bool
{
#if mobile
var returnVal = false;
for (touch in FlxG.touches.list)
{
returnVal = touch.justReleased;
}
return returnVal;
#else
return FlxG.mouse.justReleased;
#end
}
public function clickCoords():FlxPoint
{
#if mobile
var returnVal = new FlxPoint();
var i=0;
for (touch in FlxG.touches.list)
{
i++;
returnVal.x += touch.screenX;
returnVal.y += touch.screenY;
}
returnVal.x /= i;
returnVal.y /= i;
return returnVal;
#else
return new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
#end
}
override public function create()
{
hall = new FlxBackdrop("assets/images/Stage3/hall wall.png", 0, 0, true, false);
add(hall);
doors = new FlxTypedGroup<Door> ();
add(doors);
#if web
doors.add(new Door(((FlxG.width/2) - 259) + 465 + 175, (FlxG.height - 280) / 2, this, "assets/images/Stage3/door.png"));
#else
doors.add(new Door(((FlxG.width - 250-(175/2)-10) / 2) + 465 + 175, (FlxG.height - 280) / 2, this, "assets/images/Stage3/door.png"));
#end
ghost = new FlxSprite(FlxG.width / 2, FlxG.height / 2, "assets/images/Stage3/chicken ghost.png");
ghost.loadGraphic("assets/images/Stage3/chicken ghost.png", true, 75, 100);
ghost.animation.add("right", [0], 30, true);
ghost.animation.add("forward", [1], 30, true);
ghost.animation.add("back", [2], 30, true);
add(ghost);
speed = 0;
super.create();
knock = new Array();
knock.push(new FlxText(ghost.x+25, ghost.y-35, -1, "*knock*", 20));
knock.push(new FlxText(ghost.x+25, ghost.y - 85, -1, "*knock*", 20));
for (member in knock)
{
member.color = 0x000000;
add(member);
member.kill();
}
nextDoor();
}
public function nextDoor()
{
inTransit = true;
if (ghost.x <= doors.members[doorIndex].x)
{
speed = 10;
ghost.animation.play("right");
}
else
{
speed = 0;
inTransit = false;
doorIndex++;
ghost.animation.play("forward");
}
}
override public function update()
{
hall.x -= speed;
/* var i = 0;
while (i < doors.members.length)
{
var basic = doors.members[i++];
if (basic != null && basic.exists && basic.active)
{
basic.update();
}
}*/
if (inTransit)
{
nextDoor();
}
super.update();
if (justPressed()&&!inTransit)
{
if (knockCount == 2)
{
knockCount = 0;
for (member in knock)
{
member.kill();
}
doors.members[doorIndex-1].open();
FlxG.watch.add(this,"doorIndex");
nextDoor();
}
else
{
knock[knockCount].revive();
knockCount++;
}
}
}
}
And here is the Door class:
package;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.FlxG;
/**
* ...
* #author ...
*/
class Door extends FlxSprite
{
var state:GhostState;
var firstPass = true;
public function new(X:Float=0, Y:Float=0, level:GhostState, ?SimpleGraphic:Dynamic)
{
super(X, Y, SimpleGraphic);
loadGraphic("assets/images/Stage3/door.png", true, 175, 250, false);
animation.add("open", [0, 1, 2, 3, 4, 5], 30, false);
animation.add("close", [5,4,3,2,1,0], 30, false);
state = level;
//this.animation.play("open");
//state.doors.add(this);
}
public override function update():Void
{
if (firstPass)
{
if (isOnScreen())
{
state.doors.add(new Door(x + 465 + 175, (FlxG.height - 280) / 2, state));
//state.add(new Door(x+465+175, (FlxG.height - 280) / 2, state));
firstPass = false;
}
}
this.x -= state.speed;
if (this.x <= 0-this.width)
{
this.destroy();
}
}
public function open()
{
trace("open");
animation.play("open", true, 0);
}
public function close()
{
animation.play("close", true, 0);
}
}
Some information abut the code, as I'm bad at remembering to comment:
doors is a group that contains all doors in the state
doorIndex is the next door the ghost is supposed to move to next (so
doorIndex - 1 is the door it's at right now)
Why isn't it triggering? And how should I go about fixing this?

The update(elapsed:Float) function has an elapsed paremeter and inside of the function you override you must call the super.update(elapsed) parent function becase the animations are computed in this parent function.

Related

how do i make FlxAsyncLoop work for making a progress bar in HaxeFlixel?

so, i tried to make an async loop for my game (to make a progress bar) and the game crashes when the state loads...
i tried to change the loops position so they don't collide and all of the code is from the FlxAsyncLoop demo but with other variables and some other changes.
here's the code:
import flixel.FlxCamera;
import flixel.FlxG;
import flixel.FlxObject;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.addons.util.FlxAsyncLoop;
import flixel.group.FlxGroup;
import flixel.math.FlxPoint;
import flixel.math.FlxVelocity;
import flixel.text.FlxText;
import flixel.ui.FlxBar;
import flixel.util.FlxColor;
class PlayState extends FlxState
{
public static var player:FlxSprite;
var ground:FlxSprite;
var axe:FlxSprite;
var wood:FlxSprite;
var base:FlxSprite;
var txt:FlxText;
var playerPos:FlxPoint;
var enemy:FlxSprite;
var move = false;
var progressR:FlxGroup;
var progressE:FlxGroup;
var resourceGroup:FlxGroup;
var enemyGroup:FlxGroup;
var maxItems:Int = 100;
var bar1:FlxBar;
var bartxt1:FlxText;
var bar2:FlxBar;
var bartxt2:FlxText;
var loopR:FlxAsyncLoop;
var loopE:FlxAsyncLoop;
public function addR()
{
var wood = new FlxSprite(FlxG.random.int(100, 2500), FlxG.random.int(100, 1800));
wood.makeGraphic(40, 100, FlxColor.BROWN);
add(wood);
bar1.value = (resourceGroup.members.length / maxItems) * 100;
bartxt1.text = "Loading resources... " + resourceGroup.members.length + " / " + maxItems;
bartxt1.screenCenter();
}
public function addE()
{
var enemy = new FlxSprite(FlxG.random.int(300, 2500), FlxG.random.int(300, 1800));
enemy.makeGraphic(32, 32, FlxColor.RED);
add(enemy);
bar2.value = (enemyGroup.members.length / maxItems) * 100;
bartxt2.text = "Loading enemys... " + enemyGroup.members.length + " / " + maxItems;
bartxt2.screenCenter();
}
override public function create()
{
super.create();
resourceGroup = new FlxGroup(maxItems);
enemyGroup = new FlxGroup(maxItems);
loopR = new FlxAsyncLoop(maxItems, addR);
loopE = new FlxAsyncLoop(maxItems, addE);
FlxG.camera.zoom = 0.5;
playerPos = FlxPoint.get();
ground = new FlxSprite(0, 0);
ground.makeGraphic(2500, 1800, FlxColor.GREEN);
add(ground);
player = new FlxSprite(100, 100);
player.loadGraphic(AssetPaths.n1__png);
axe = new FlxSprite(player.x + 60, player.y);
axe.loadGraphic(AssetPaths.axeR__png);
camera = new FlxCamera(0, 0, 2500, 1800);
camera.bgColor = FlxColor.TRANSPARENT;
camera.setScrollBoundsRect(0, 0, ground.width, ground.height);
FlxG.cameras.reset(camera);
camera.target = player;
if (FlxG.collide(wood, player))
FlxObject.separate(wood, player);
if (FlxG.collide(wood, enemy))
FlxObject.separate(wood, enemy);
if (FlxG.collide(enemy, player))
FlxObject.separate(enemy, player);
progressR = new FlxGroup();
bar1 = new FlxBar(0, 0, LEFT_TO_RIGHT, FlxG.width, 50, null, "", 0, 100, true);
bar1.value = 0;
bar1.screenCenter();
progressR.add(bar1);
bartxt1 = new FlxText(0, 0, FlxG.width, "Loading resources... 0 / " + maxItems);
bartxt1.setFormat(null, 28, FlxColor.WHITE, CENTER, OUTLINE);
bartxt1.screenCenter();
progressR.add(bartxt1);
progressE = new FlxGroup();
bar2 = new FlxBar(0, 0, LEFT_TO_RIGHT, FlxG.width, 50, null, "", 0, 100, true);
bar2.value = 0;
bar2.screenCenter();
progressE.add(bar2);
bartxt2 = new FlxText(0, 0, FlxG.width, "Loading enemys... 0 / " + maxItems);
bartxt2.setFormat(null, 28, FlxColor.WHITE, CENTER, OUTLINE);
bartxt2.screenCenter();
progressE.add(bartxt2);
resourceGroup.visible = false;
resourceGroup.active = false;
enemyGroup.visible = false;
enemyGroup.active = false;
add(progressR);
add(progressE);
add(resourceGroup);
add(enemyGroup);
add(loopR);
}
override public function update(elapsed:Float)
{
super.update(elapsed);
if (FlxG.keys.pressed.LEFT && move)
{
player.x -= 5;
axe.loadGraphic(AssetPaths.axeL__png);
}
if (FlxG.keys.pressed.RIGHT && move)
{
player.x += 5;
axe.loadGraphic(AssetPaths.axeR__png);
}
if (FlxG.keys.pressed.UP && move)
{
player.y -= 5;
}
if (FlxG.keys.pressed.DOWN && move)
{
player.y += 5;
}
axe.x = player.x + 60;
axe.y = player.y;
playerPos = FlxPoint.get();
playerPos = player.getMidpoint();
FlxVelocity.moveTowardsPoint(enemy, playerPos, 70);
if (!loopR.started)
{
loopR.start();
}
else
{
if (loopR.finished)
{
resourceGroup.visible = true;
progressR.visible = false;
resourceGroup.active = true;
progressR.active = false;
loopR.kill();
loopR.destroy();
add(loopE);
loopE.start();
}
}
if (loopE.finished)
{
move = true;
add(player);
add(axe);
enemyGroup.visible = true;
progressE.visible = false;
enemyGroup.active = true;
progressE.active = false;
loopE.kill();
loopE.destroy();
}
}
}
i'm showing everything because of the functions and other things that can make this problem
(my english is bad sorry if i miss something...)
Without knowing the exact error, I suspect that the problem is when you call
if (FlxG.collide(wood, player))
FlxObject.separate(wood, player);
if (FlxG.collide(wood, enemy))
FlxObject.separate(wood, enemy);
if (FlxG.collide(enemy, player))
FlxObject.separate(enemy, player);
Inside your create function - wood and enemy are declared in other functions and do not exist there.
There are a couple of things I would do differently here:
(Note: I didn't TEST this code, so there may still be problems, but this might help get you pointed in the right direction...)
class PlayState extends FlxState
{
public static var player:FlxSprite;
var ground:FlxSprite;
var axe:FlxSprite;
var base:FlxSprite;
var txt:FlxText;
var playerPos:FlxPoint;
var move:Bool = false;
var progressR:FlxGroup;
var progressE:FlxGroup;
var resourceGroup:FlxTypedGroup<FlxSprite>;
var enemyGroup:FlxTypedGroup<FlxSprite>;
var maxItems:Int = 100;
var bar1:FlxBar;
var bartxt1:FlxText;
var bar2:FlxBar;
var bartxt2:FlxText;
var loopR:FlxAsyncLoop;
var loopE:FlxAsyncLoop;
public function addR()
{
var wood = new FlxSprite(FlxG.random.int(100, 2500), FlxG.random.int(100, 1800));
wood.makeGraphic(40, 100, FlxColor.BROWN);
resourceGroup.add(wood);
bar1.value = (resourceGroup.members.length / maxItems) * 100;
bartxt1.text = "Loading resources... " + resourceGroup.members.length + " / " + maxItems;
bartxt1.screenCenter();
FlxG.collide(player, resourceGroup) // should not need to call `seperate` - it's automatic when using `collide` vs `overlap`
}
public function addE()
{
var enemy = new FlxSprite(FlxG.random.int(300, 2500), FlxG.random.int(300, 1800));
enemy.makeGraphic(32, 32, FlxColor.RED);
enemyGroup.add(enemy);
FlxG.collide(enemyGroup, resourceGroup)
FlxG.collide(player, resourceGroup)
bar2.value = (enemyGroup.members.length / maxItems) * 100;
bartxt2.text = "Loading enemys... " + enemyGroup.members.length + " / " + maxItems;
bartxt2.screenCenter();
}
override public function create()
{
super.create();
resourceGroup = new FlxTypedGroup<FlxSprite>(maxItems);
enemyGroup = new FlxTypedGroup<FlxSprite>(maxItems);
loopR = new FlxAsyncLoop(maxItems, addR);
loopE = new FlxAsyncLoop(maxItems, addE);
FlxG.camera.zoom = 0.5;
playerPos = FlxPoint.get();
ground = new FlxSprite(0, 0);
ground.makeGraphic(2500, 1800, FlxColor.GREEN);
add(ground);
player = new FlxSprite(100, 100);
player.loadGraphic(AssetPaths.n1__png);
axe = new FlxSprite(player.x + 60, player.y);
axe.loadGraphic(AssetPaths.axeR__png);
camera = new FlxCamera(0, 0, 2500, 1800);
camera.bgColor = FlxColor.TRANSPARENT;
camera.setScrollBoundsRect(0, 0, ground.width, ground.height);
FlxG.cameras.reset(camera);
camera.target = player;
progressR = new FlxGroup();
bar1 = new FlxBar(0, 0, LEFT_TO_RIGHT, FlxG.width, 50, null, "", 0, 100, true);
bar1.value = 0;
bar1.screenCenter();
progressR.add(bar1);
bartxt1 = new FlxText(0, 0, FlxG.width, "Loading resources... 0 / " + maxItems);
bartxt1.setFormat(null, 28, FlxColor.WHITE, CENTER, OUTLINE);
bartxt1.screenCenter();
progressR.add(bartxt1);
progressE = new FlxGroup();
bar2 = new FlxBar(0, 0, LEFT_TO_RIGHT, FlxG.width, 50, null, "", 0, 100, true);
bar2.value = 0;
bar2.screenCenter();
progressE.add(bar2);
bartxt2 = new FlxText(0, 0, FlxG.width, "Loading enemys... 0 / " + maxItems);
bartxt2.setFormat(null, 28, FlxColor.WHITE, CENTER, OUTLINE);
bartxt2.screenCenter();
progressE.add(bartxt2);
resourceGroup.visible = false;
resourceGroup.active = false;
enemyGroup.visible = false;
enemyGroup.active = false;
add(progressR);
add(progressE);
add(resourceGroup);
add(enemyGroup);
add(loopR);
}
public function gamePlay(elapsed:Float):Void
{
if (FlxG.keys.pressed.LEFT && move)
{
player.x -= 5; // why +/- position and not .velocity?
// THIS is probably not right - you want to use a sprite sheet with animations and call axe.play("left") or something...
axe.loadGraphic(AssetPaths.axeL__png);
}
if (FlxG.keys.pressed.RIGHT && move)
{
player.x += 5;
axe.loadGraphic(AssetPaths.axeR__png);
}
if (FlxG.keys.pressed.UP && move)
{
player.y -= 5;
}
if (FlxG.keys.pressed.DOWN && move)
{
player.y += 5;
}
axe.x = player.x + 60;
axe.y = player.y;
playerPos = FlxPoint.get();
playerPos = player.getMidpoint();
for (e in enemyGroup)
{
FlxVelocity.moveTowardsPoint(e, playerPos, 70);
}
}
public function loading(elapsed:Float):Void
{
if (!loopR.started)
{
loopR.start();
}
else if (loopR.finished)
{
resourceGroup.visible = true;
progressR.visible = false;
resourceGroup.active = true;
progressR.active = false;
loopR.kill();
loopR.destroy();
add(loopE);
loopE.start();
}
else if (loopE.finished)
{
move = true;
add(player);
add(axe);
enemyGroup.visible = true;
progressE.visible = false;
enemyGroup.active = true;
progressE.active = false;
loopE.kill();
loopE.destroy();
}
}
override public function update(elapsed:Float)
{
super.update(elapsed);
if (!move)
{
loading(elapsed);
}
else
{
gamePlay(elapsed);
}
}
}

Wren class does not implement a field

I'm trying to learn how to use Dome and Wren. To do this I've started working on a simple Flappy Bird clone.
The problem I'm having is that I get the error message
Bird does not implement bird_idle
It then points to line 63 in my main class which is shown below:
class Main {
resources=(value){ _resources = value }
bird=(value){ _bird = value }
construct new() {
_resources = Resources.new()
_bird = Bird.new(_resources.birdIdle, _resources.birdFlap, _resources.obstacleTile.width * 2, _resources.obstacleTile.height * 4, 10, 4)
}
init() {}
update() {}
draw(alpha) {
Canvas.cls()
Canvas.draw(_bird.bird_idle, _bird.center.x, _bird.center.y) <-- this is line 63
}
}
var Game = Main.new()
Since I'm new to Wren I don't quite understand what this means seeing as if you look at my bird class below, I should be implementing bird_idle. So what am I doing wrong?
class Bird {
bird_idle=(value){ _bird_idle = value } <-- Right?
bird_flap=(value){ _bird_flap = value }
center=(value){ _center = value }
gravity=(value){ _gravity = value }
force=(value){ _force = value }
velocity=(value){ _velocity = value }
velocityLimit=(value){ _velocityLimit = value }
isGameRunning=(value){ _isGameRunning = value }
construct new(idle, flap, horizontalPosition, verticalPosition, drag, jumpForce) {
_bird_idle = idle
_bird_flap = flap
_center = Vector.new(horizontalPosition + (idle.width * 0.5), verticalPosition + (idle.height*0.5))
_gravity = drag
_force = jumpForce
_velocityLimit = 1000
_isGameRunning = true
}
jump() {
_velocity = -_force
}
isTouchingCeiling() {
var birdTop = _center.y - (_bird_idle.height * 0.5)
if(birdTop < 0) {
return true
}
return false
}
isTouchingGround() {
var birdBottom = _center.y + (_bird_idle.height * 0.5)
if(birdBottom > height) {
return true
}
return false
}
}
You forgot to add the getter:
class Bird {
construct new(idle) {
_bird_idle = idle
}
bird_idle=(value){_bird_idle = value }
bird_idle{_bird_idle} // You need this if you want to access the field _bird_idle.
}
var my_bird = Bird.new("Idle")
my_bird.bird_idle = "Not Idle"
System.print(my_bird.bird_idle) // Output: Not Idle

Error: It looks like you're mixing "active" and "Static" modes in Processing

The code is an open processing program which I downloaded but doesn't seem to be working. I am a beginner and need help in understanding what to do with the error. Thanks in advance.
Please find the openprocessing code here: https://www.openprocessing.org/sketch/407405
void setup() {
size(400,400,0);
}
rectMode(CENTER);
textAlign(CENTER,CENTER);
var P=200;
var LOSE=false;
var score=0;
var particlestor = [];
var Timer=millis();
var fall = function(position) {
this.velocity = new PVector(0,3);
this.position = position.get();
fall.prototype.run = function() {
this.position.add(this.velocity);
noStroke();
fill(0, 0,0);
rect(this.position.x, this.position.y, 20, 20);
if(dist(this.position.x, this.position.y,P,390)<=20){LOSE=true;}};
fall.prototype.isDead = function() {
if (this.position.y > 400) {return true;} else {return false;}
};};
for(var i=0;i<=4;i++){particlestor.push(new fall(new PVector(random(0,400), random(-10,-600))));}
draw = function() {
if(LOSE===false){
background(255, 255, 255);
if(millis()-Timer>=1000){
Timer=millis();
score+=1;
particlestor.push(new fall(new PVector(random(0,400), random(-10,-400))));
}
P=mouseX;
for (var i = particlestor.length-1; i >= 0; i--) {
var p = particlestor[i];
p.run();
if (p.isDead()===true) {
particlestor.splice(i, 1);
particlestor.push(new fall(new PVector(random(0,400), random(-10,-400))));
}}
fill(240,0,0);
rect(P,390,20,20);
text(score,10,10);
if(P>400){LOSE=true;}
if(P<0){LOSE=true;}
}
if(LOSE===true){
textSize(60);
text("YOU LOSE\n score :"+score,200,200);
}};// 50 lines
The code above uses ProcessingJS. If you want to run the code locally on your machine you have a few options:
Have a look at the ProcessingJS QuickStart guides and use that
Port the code to Processing
Port the code to p5.js
For example:
var P=200;
var LOSE=false;
var score=0;
var particlestor = [];
var Timer;
function setup() {
createCanvas(400, 400, 0);
rectMode(CENTER);
textAlign(CENTER, CENTER);
Timer=millis();
for (var i=0; i<=4; i++) {
particlestor.push(new fall(createVector(random(0, 400), random(-10, -600))));
}
}
function draw() {
if (LOSE===false) {
background(255, 255, 255);
if (millis()-Timer>=1000) {
Timer=millis();
score+=1;
particlestor.push(new fall(createVector(random(0, 400), random(-10, -400))));
}
P=mouseX;
for (var i = particlestor.length-1; i >= 0; i--) {
var p = particlestor[i];
p.run();
if (p.isDead()===true) {
particlestor.splice(i, 1);
particlestor.push(new fall(createVector(random(0, 400), random(-10, -400))));
}
}
fill(240, 0, 0);
rect(P, 390, 20, 20);
text(score, 10, 10);
if (P>400) {
LOSE=true;
}
if (P<0) {
LOSE=true;
}
}
if (LOSE===true) {
textSize(60);
text("YOU LOSE\n score :"+score, 200, 200);
}
}
var fall = function(position) {
this.velocity = createVector(0, 3);
this.position = position.copy();
fall.prototype.run = function() {
this.position.add(this.velocity);
noStroke();
fill(0, 0, 0);
rect(this.position.x, this.position.y, 20, 20);
if (dist(this.position.x, this.position.y, P, 390)<=20) {
LOSE=true;
}
};
fall.prototype.isDead = function() {
if (this.position.y > 400) {
return true;
} else {
return false;
}
};
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.min.js"></script>
I recommend refactoring (cleaning the code, naming variables more meaningfully/consistent, commenting code sections, etc).
This would make it easy to understand the code and remix/adapt it to something better.

Invalid Array Width without declaring new dimension

My web app is generating an "Invalid Array Width" error at line 462 of Crossfilter.js v1.3.12. This error seems to tell me I have >32 dimensions. The puzzle is that I am not knowingly declaring a new dimension when the error occurs.
I have 10 slider bars, which act as numeric filters on my dataset. At the end of a drag event on the second slider bar, a dimension is declared if none already exists at the second location within the numericDims array. (Edit: even when I declare all the 10 dimensions in advance, and remove the dynamic declaration, the problem still occurs.) About 10 dimensions already exist in the app for other graphics & filters.
The first time I move a slider handle, "new dimension" is logged. After that, every time I move a handle on the same slider, "new dimension" is not logged. This is expected behaviour. But if I move the handles enough times, I get the "Invalid Array Width" error. So, I think I must be accidentally declaring a new dimension every time I move a handle. Can anyone see how I am unwittingly declaring a new dimension? The most relevant code:
if (!numericDims[tempIndex]) {
console.log('new dimension');
numericDims[tempIndex] = facts.dimension(function(p){ return p[d]; });
}
if (flag==0) {
prt.classed("activeFilter",true);
numericDims[tempIndex].filterFunction(function(p){ return p>=min && p<=max; });
} else {
prt.classed("activeFilter",false);
numericDims[tempIndex].filterAll();
// numericDims[tempIndex].dispose(); ***I figure it's quicker to store them instead of disposing/deleting. Even when I dispose/delete, the problem still happens.
// delete numericDims[tempIndex];
// numericDims.splice(tempIndex,1);
prt.selectAll("g.handle.left").attr("title",null);
prt.selectAll("g.handle.right").attr("title",null);
}
console.log(numericDims);
Full function:
function dragended(d) {
let transformation = {
Y: Math.pow(10, 24),
Z: Math.pow(10, 21),
E: Math.pow(10, 18),
P: Math.pow(10, 15),
T: Math.pow(10, 12),
G: Math.pow(10, 9),
M: Math.pow(10, 6),
k: Math.pow(10, 3),
h: Math.pow(10, 2),
da: Math.pow(10, 1),
d: Math.pow(10, -1),
c: Math.pow(10, -2),
m: Math.pow(10, -3),
μ: Math.pow(10, -6),
n: Math.pow(10, -9),
p: Math.pow(10, -12),
f: Math.pow(10, -15),
a: Math.pow(10, -18),
z: Math.pow(10, -21),
y: Math.pow(10, -24)
}
let reverse = s => {
let returnValue;
Object.keys(transformation).some(k => {
if (s.indexOf(k) > 0) {
returnValue = parseFloat(s.split(k)[0]) * transformation[k];
return true;
}
})
return returnValue;
}
var facts = window.facts;
if (d3.select(this).attr("class").indexOf("left")==-1) { var otherHandle = 'left'; } else { var otherHandle = 'right'; }
d3.select(this).classed("dragging",false);
var filterFields = window.filterFields;
var tempIndex = filterFields[0].indexOf(d);
var min = filterFields[2][tempIndex];
var max = filterFields[3][tempIndex];
//console.log(min+', '+max);
var scale = filterFields[4][tempIndex];
var t = d3.transform(d3.select(this).attr("transform"));
var thisX = t.translate[0];
var flag=0;
var prt = d3.select("g#f_"+tempIndex);
var leftHandleX = d3.transform(prt.selectAll("g.handle.left").attr("transform")).translate[0];
var rightHandleX = d3.transform(prt.selectAll("g.handle.right").attr("transform")).translate[0];
var wid = prt.selectAll("g.axis").select("rect.numFilterBox").attr("width");
prt.selectAll("g.axis").select("rect.numFilterBox").attr("x",leftHandleX).attr("width",rightHandleX - leftHandleX);
var num = -1;
var pFlag = 0;
if (filterFields[3][tempIndex]<=1) { var fmt = d3.format('%'); pFlag=1; } else { var fmt = d3.format('4.3s'); }
if (otherHandle=='left') {
if (thisX>=300 && scale(min)==0) { flag=1; }
max = scale.invert(thisX);
if (isNaN(+fmt(max).trim())) {
if (pFlag==1) {
max = +fmt(max).substr(0,fmt(max).length-1)/100
} else {
max = reverse(fmt(max));
}
} else {
max = +fmt(max).trim();
}
prt.selectAll("g.handle.right").attr("title",function(d){ return 'The filtered maximum for '+filterFields[1][tempIndex]+' is '+max; });
} else {
if (thisX<=0 && scale(max)==300) { flag=1; }
min = scale.invert(thisX);
if (isNaN(+fmt(min).trim())) {
if (pFlag==1) {
min = +fmt(min).substr(0,fmt(min).length-1)/100
} else {
min = reverse(fmt(min));
}
} else {
min = +fmt(min).trim();
}
prt.selectAll("g.handle.left").attr("title",function(d){ return 'The filtered minimum for '+filterFields[1][tempIndex]+' is '+min; });
}
filterFields[2][tempIndex] = min;
filterFields[3][tempIndex] = max;
window.filterFields = filterFields;
if (!numericDims[tempIndex]) {
console.log('new dimension');
numericDims[tempIndex] = facts.dimension(function(p){ return p[d]; });
}
if (flag==0) {
prt.classed("activeFilter",true);
numericDims[tempIndex].filterFunction(function(p){ return p>=min && p<=max; });
} else {
prt.classed("activeFilter",false);
numericDims[tempIndex].filterAll();
// numericDims[tempIndex].dispose();
// delete numericDims[tempIndex];
// numericDims.splice(tempIndex,1);
prt.selectAll("g.handle.left").attr("title",null);
prt.selectAll("g.handle.right").attr("title",null);
}
console.log(numericDims);
update();
doHighlight();
window.dragFlag=1;
}

how to change IViewport verticalScrollPosition dynamicly

I'm trying to scroll VGroup with scroller:
<s:Scroller id="scroller" width="100" height="100">
<s:VGroup id="vp" width="100%" height="100%">
<my:TripView id="one"/>
<my:TripView id="two"/>
// if any more TripView.....
</s:VGroup>
</s:Scroller>
The TripView is dynamiclly generated, so the VGroup contentHeight may much greater than viewPortHeight. Since I could drag stuff in the TripView, I want to change the vp.verticalScrollPosition when the drag stuff almost move to the bottom of the view so the other TripView could be in the screen.
The most important thing is the scrollRect. Change the verticalScrollPosition based on the scrollRect. To use the ScrollManager, you should register viewport by registerViewport function. Then listen for mouseMove event, in the event listener invoke startScroll. Following is implementation:
package utils {
import flash.display.Stage;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import mx.core.IInvalidating;
import spark.components.Group;
public class ScrollManager {
private var viewport:Group;
private var stage:Stage;
private var oldMovingMouseY:Number;
private static var _instance:ScrollManager;
//threshold for scrolling
private const FUDGE:Number = 35;
//scroll up speed
private const UP_SCROLL_DELTA:int = 50;
//scroll down speed
private const DOWN_SCROLL_DELTA:int = 80;
public function registerViewport(viewport:Group):void {
this.viewport = viewport;
this.stage = viewport.stage;
}
public static function getInstance():ScrollManager {
if(_instance == null) {
_instance = new ScrollManager();
}
return _instance;
}
public function startScroll(mouseEvent:MouseEvent):void {
oldMovingMouseY = mouseEvent.stageY;
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove, false, 0, true);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp, false, 0, true);
}
private function onMouseUp(event:MouseEvent):void {
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
if (viewport is IInvalidating) {
//viewport.callLater(IInvalidating(viewport).validateNow);
//change VSP on scrollRect.y
var rect:Rectangle = viewport.scrollRect;
viewport.verticalScrollPosition = rect.y;
trace("========final vsp ========", rect.y);
}
}
private function onMouseMove(event:MouseEvent):void {
var currentMouseX:Number = event.stageX;
var currentMouseY:Number = event.stageY;
trace("mouseY ", currentMouseY);
//scroll direction
var delta:Number = currentMouseY - oldMovingMouseY;
var direction:int = (delta > 0) ? 1 : (delta < 0) ? -1: 0;
var scrollDelta:Number = direction > 0 ? DOWN_SCROLL_DELTA : UP_SCROLL_DELTA;
//current mousePoint in viewport coordination
var localPoint:Point = viewport.globalToLocal(new Point(currentMouseX, currentMouseY));
trace("localPoint: ", localPoint);
var scrollRect:Rectangle = viewport.scrollRect;
trace("viewport rect", scrollRect);
//determine if need scroll
if(needScroll(localPoint, scrollRect, direction)) {
trace("direction ", direction > 0 ? " UP": " DOWN");
scrollRect.y += scrollDelta*direction;
viewport.scrollRect = scrollRect;
if (viewport is IInvalidating) {
IInvalidating(viewport).validateNow();
}
}
oldMovingMouseY = currentMouseY;
}
private function needScroll(localPoint:Point, scrollRect:Rectangle, direction:int):Boolean {
var localY:Number = localPoint.y;
var bottom:Number = scrollRect.bottom;
var top:Number = scrollRect.top;
if(direction > 0 && (localY + FUDGE) > bottom) {
return true;
}
if(direction< 0 && (localY - FUDGE) < top) {
return true;
}
return false;
}
}
}

Resources