How to create a spin box in dm-script? - user-interface

I would like to create a spin box on a modal/modeless dialog in dm-script, which enables users to increase or decrease the number value in the text field by clicking up or down arrow buttons (i.e., spin buttons).
Is there an appropriate way to create such a spin box? It will be appreciated if you share some wisdom. Thank you very much in advance.

There exists no "spin control" for scripted dialogs.
However, you can build a proxy-spin control by creating and arranging according push-buttons. It is a bit crude, but the following code creates this:
Class CMySpin : UIFrame
{
TagGroup CreateDLGTgs( object self )
{
TagGroup DLGtgs, DLGItems
DLGtgs = DLGCreateDialog( "Test", DLGItems )
TagGroup upButton = DLGCreatePushButton( "U", "OnPushUp" ).DLGExternalPadding(0,-5).DLGInternalPadding(-2,-3)
TagGroup downButton = DLGCreatePushButton( "D", "OnPushDown" ).DLGInternalPadding(-2,-3)
TagGroup field = DLGCreateIntegerField( 10, 10 ).DLGIdentifier( "field" )
TagGroup SpinGroup = DLGGroupItems( upButton, downButton ).DLGTableLayout(1,2,0)
TagGroup fieldWithSpin = DLGGroupItems( field, SpinGroup ).DLGTableLayout(2,1,0)
DLGItems.DLGAddElement( fieldWithSpin )
return DLGtgs
}
void OnPushUp( object self )
{
taggroup fieldTG = self.LookupElement( "field" )
number value = fieldTG.DLGGetValue()
value++
fieldTG.DLGValue( value )
}
void OnPushDown( object self )
{
taggroup fieldTG = self.LookupElement( "field" )
number value = fieldTG.DLGGetValue()
value--
fieldTG.DLGValue( value )
}
void CreateAndPose( object self )
{
self.Init( self.CreateDLGTgs() )
self.Pose()
}
}
Alloc(CMySpin).CreateAndPose()
You can then play with looks a bit by using bitmap buttons instead of simple push buttons and setting things up until they look more appealing.
f.e. I created this variant:
With this code:
Class CMySpin : UIFrame
{
TagGroup CreateDLGTgs( object self )
{
image arrowImg := [7,5]:
{ { 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 1, 1, 1, 0, 0 },
{ 0, 1, 1, 1, 1, 1, 0 },
{ 0, 0, 0, 0, 0, 0, 0 } }
number factor = 2
image upArrow := RealImage("",4,factor*7,factor*5)
upArrow=arrowImg.warp( icol / factor, irow / factor )
image downArrow = upArrow
downArrow.FlipVertical()
rgbImage upArrowUp = RGB( upArrow * 100, upArrow * 100, upArrow * 100 )
rgbImage upArrowDown = RGB( upArrow * 200, upArrow * 200, upArrow * 200 )
rgbImage downArrowUp = RGB( downArrow * 100, downArrow * 100, downArrow * 100 )
rgbImage downArrowDown = RGB( downArrow * 200, downArrow * 200, downArrow * 200 )
TagGroup DLGtgs, DLGItems
DLGtgs = DLGCreateDialog( "Test", DLGItems )
TagGroup upButton = DLGCreateBevelButton( upArrowUp, upArrowDown, "OnPushUp" ).DLGExternalPadding(0,-3).DLGInternalPadding(-2,-3)
TagGroup downButton = DLGCreateBevelButton( downArrowUp, downArrowDown, "OnPushDown" ).DLGExternalPadding(0,-3).DLGInternalPadding(-2,-3)
TagGroup field = DLGCreateIntegerField( 10, 10 ).DLGIdentifier( "field" )
TagGroup SpinGroup = DLGGroupItems( upButton, downButton ).DLGTableLayout(1,2,0)
TagGroup fieldWithSpin = DLGGroupItems( field, SpinGroup ).DLGTableLayout(2,1,0)
DLGItems.DLGAddElement( fieldWithSpin )
return DLGtgs
}
void OnPushUp( object self )
{
taggroup fieldTG = self.LookupElement( "field" )
number value = fieldTG.DLGGetValue()
value++
fieldTG.DLGValue( value )
}
void OnPushDown( object self )
{
taggroup fieldTG = self.LookupElement( "field" )
number value = fieldTG.DLGGetValue()
value--
fieldTG.DLGValue( value )
}
void CreateAndPose( object self )
{
self.Init( self.CreateDLGTgs() )
self.Pose()
}
}
Alloc(CMySpin).CreateAndPose()

Related

How to change color of each controlP5 dropdown list entry individually?

Using the following MWE:
import controlP5.*;
import java.util.*;
ControlP5 cp5;
void setup() {
size(400, 400);
cp5 = new ControlP5(this);
List l = Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h");
/* add a ScrollableList, by default it behaves like a DropdownList */
cp5.addScrollableList("dropdown")
.setPosition(100, 100)
.setSize(200, 100)
.setBarHeight(20)
.setItemHeight(20)
.addItems(l)
// .setType(ScrollableList.LIST) // currently supported DROPDOWN and LIST
;
}
void draw() {
background(240);
}
How can I change the font color of each list entry separately? I assume I'll have to use a for loop of some kind like the following
for (int i =0; i < myarray.length; i++){
dropdown.setColorActive(elementDetermine(myarray[i]));
}
Where elementDetermine() takes an integer and returns a color. Unfortunately, when I run this loop in either the setup or the draw function, the dropdown list doesn't change without error message.
Unfortunately there's no easy readily available method to change the font color of each list entry separately.
As you can see in the documentation the available methods access the main caption which applies to all items.
In fact, the same Label component is re-used accross all list items and simply re-rendered once per item (changing current text/colours) as you can see in the source code
If you really really need to change the font color you can, but that will be quite a few OOP hoops to jump through (since there is no array of Label instances per item):
you'd need to make a custom ControllerView< ScrollableList > to override it's display() method
for the custom display() to work the same as the original ScrollableList you need to pretty much replicate the super class
the ScrollableList super class has a bunch of private properties that can easily be accessed from the ScrollableListView class since it's part of ScrollableList, however in our case all those private / protected properties that need to be accessed in display() need to be accessible. To do this a ScrollableList subclass is implemenented (PopUpScrollableList) which mainly replicates it's superclass behaviours wherever those private/protected properties are used in display() and also makes them available.
Finally the custom scrollable list can have a color[] which can store the custom colours so they can be accessed and rendered in the overriden display() method:
import controlP5.*;
// used by the custom scrollable list view
import static controlP5.ControlP5.b;
import java.util.*;
ControlP5 cp5;
void setup() {
size(400, 400);
cp5 = new ControlP5(this);
List l = Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h");
/* add a custom ScrollableList, by default it behaves like a DropdownList */
PopUpScrollableList dropdown = addPopUpScrollableList("dropdown");
dropdown.setPosition(100, 100)
.setSize(200, 100)
.setBarHeight(20)
.setItemHeight(20)
.addItems(l)
// .setType(ScrollableList.LIST) // currently supported DROPDOWN and LIST
;
// a list of (random) colourr: a colour per item
color[] textColors = new color[l.size()];
for(int i = 0 ; i < textColors.length; i++){
textColors[i] = color(255, random(255), random(255), random(255));
}
// set custom text colours: this is a bit hacky: normally you'd check if items.size() matches textColors.length, etc.
dropdown.textColors = textColors;
// set a custom view for the list
dropdown.setView(makeCustomScrollListView());
}
void draw() {
background(240);
}
// simply adds our custom scrollable list
PopUpScrollableList addPopUpScrollableList( final String theName ) {
PopUpScrollableList myController = new PopUpScrollableList(cp5, theName);
return myController;
}
ControllerView< ScrollableList > makeCustomScrollListView(){
// make an custom scrollable list view on the fly and access the fileds it needs
return new ControllerView< ScrollableList >() {
// tweaked version of https://github.com/sojamo/controlp5/blob/1f7cb649865eb8657495b5cfeddd0dbe85d70cac/src/controlP5/ScrollableList.java#L391
public void display( PGraphics g , ScrollableList c ) {
// setHeight( -200 ); /* UP */
PopUpScrollableList d = (PopUpScrollableList)c;
g.noStroke( );
if ( c.isBarVisible( ) ) {
boolean b = d.itemHover() == -1 && d.isInside() && !d.isDragged();
g.fill( b ? c.getColor( ).getForeground( ) : c.getColor( ).getBackground( ) );
g.rect( 0 , 0 , c.getWidth( ) , c.getBarHeight() );
g.pushMatrix( );
g.translate( c.getWidth( ) - 8 , c.getBarHeight() / 2 - 2 );
g.fill( c.getColor( ).getCaptionLabel( ) );
if ( c.isOpen( ) ) {
g.triangle( -3 , 0 , 3 , 0 , 0 , 3 );
} else {
g.triangle( -3 , 3 , 3 , 3 , 0 , 0 );
}
g.popMatrix( );
c.getCaptionLabel( ).draw( g , 4 , c.getBarHeight() / 2 );
}
if ( c.isOpen( ) ) {
int bar = ( c.isBarVisible( ) ? c.getBarHeight() : 0 );
int h = ( ( d.updateHeight( ) ) );
g.pushMatrix( );
// g.translate( 0 , - ( h + bar +
// c.itemSpacing ) ); /* UP */
g.fill( c.getBackgroundColor( ) );
g.rect( 0 , bar , c.getWidth( ) , h );
g.pushMatrix( );
g.translate( 0 , ( bar == 0 ? 0 : ( c.getBarHeight() + d.itemSpacing() ) ) );
/* draw visible items */
c.updateItemIndexOffset( );
int m0 = d.itemIndexOffset;
List items = c.getItems();
int m1 = items.size( ) > d.itemRange() ? ( d.itemIndexOffset + d.itemRange() ) : items.size( );
for ( int i = m0 ; i < m1 ; i++ ) {
Map< String , Object > item = (Map< String , Object >) items.get( i );
CColor itemColor = ( CColor ) item.get( "color" );
g.fill( ( b( item.get( "state" ) ) ) ? itemColor.getActive( ) : ( i == d.itemHover() ) ? ( c.isMousePressed() ? itemColor.getActive( ) : itemColor.getForeground( ) ) : itemColor.getBackground( ) );
float boxY = d.itemHeight() - 1;
g.rect( 0 , 0 , c.getWidth( ) , boxY );
Label label = c.getValueLabel( );
// finally set custom text colour
if(d.textColors != null){
label.setColor(d.textColors[i]);
}
label.set( item.get( "text" ).toString( ) ).draw( g , 4 , d.itemHeight() / 2 );
g.translate( 0 , d.itemHeight() );
}
g.popMatrix( );
if ( c.isInside() ) {
int m = items.size( ) - d.itemRange();
if ( m > 0 ) {
g.fill( c.getColor( ).getCaptionLabel( ) );
g.pushMatrix( );
int s = 4; /* spacing */
int s2 = s / 2;
g.translate( c.getWidth( ) - s , c.getBarHeight() );
int len = ( int ) PApplet.map( ( float ) Math.log( m * 10 ) , 0 , 10 , h , 0 );
int pos = ( int ) ( PApplet.map( d.itemIndexOffset , 0 , m , s2 , h - len - s2 ) );
g.rect( 0 , pos , s2 , len );
g.popMatrix( );
}
}
g.popMatrix( );
}
}
};
}
// a custom ScrollableList subclass: mainly it needs to expose properties the custom view (via setView()) can't access in display()
class PopUpScrollableList extends ScrollableList{
private int itemIndexOffset = 0;
private int _myType = DROPDOWN;
protected boolean isOpen = true;
public color[] textColors;
PopUpScrollableList(ControlP5 cp5, String name){
super(cp5, name);
println("custom PopUpScrollableList named " + name + " constructed");
}
public boolean isOpen( ) {
return isOpen;
}
public ScrollableList open( ) {
return setOpen( true );
}
public ScrollableList close( ) {
return setOpen( false );
}
public ScrollableList setOpen( boolean b ) {
isOpen = b;
return this;
}
public int itemHover(){
return itemHover;
}
public int itemSpacing(){
return 1;
}
public int itemRange(){
return itemRange;
}
public int itemHeight(){
return itemHeight;
}
public boolean isInside(){
return isInside;
}
public boolean isDragged(){
return isDragged;
}
public int barHeight(){
return barHeight;
}
protected int updateHeight( ) {
itemRange = ( PApplet.abs( getHeight( ) ) - ( isBarVisible( ) ? barHeight : 0 ) ) / itemHeight;
return itemHeight * ( items.size( ) < itemRange ? items.size( ) : itemRange );
}
public List< Map< String , Object > > items(){
return items;
}
#Override protected void onRelease( ) {
if ( !isDragged ) {
if ( getPointer( ).y( ) >= 0 && getPointer( ).y( ) <= barHeight ) {
setOpen( !isOpen( ) );
} else if ( isOpen ) {
double n = Math.floor( ( getPointer( ).y( ) - barHeight ) / itemHeight );
// n += itemRange; /* UP */
int index = ( int ) n + itemIndexOffset;
updateIndex( index );
}
}
}
private void updateIndex( int theIndex ) {
if ( theIndex >= items.size( ) ) {
return;
}
Map m = items.get( theIndex );
switch ( _myType ) {
case ( LIST ):
super.setValue( theIndex );
for ( Object o : items ) {
( ( Map ) o ).put( "state" , false );
}
m.put( "state" , !ControlP5.b( m.get( "state" ) ) );
break;
case ( DROPDOWN ):
super.setValue( theIndex );
setOpen( false );
getCaptionLabel( ).setText( ( m.get( "text" ).toString( ) ) );
break;
case ( CHECKBOX ):
m.put( "state" , !ControlP5.b( m.get( "state" ) ) );
break;
}
}
public ScrollableList setValue( float theValue ) {
updateIndex( ( int ) ( theValue ) );
return this;
}
#Override protected void onDrag( ) {
scroll( getPointer( ).dy( ) );
}
#Override protected void onScroll( int theValue ) {
scroll( theValue );
}
private void scroll( int theValue ) {
if ( isOpen() ) {
itemIndexOffset += theValue;
itemIndexOffset = ( int ) ( Math.floor( Math.max( 0 , Math.min( itemIndexOffset , items.size( ) - itemRange ) ) ) );
itemHover = -2;
}
}
#Override protected void onLeave( ) {
itemHover = -1;
}
#Override protected void onEnter( ) {
updateHover( );
}
#Override protected void onMove( ) {
updateHover( );
}
#Override protected void onEndDrag( ) {
updateHover( );
}
private void updateHover( ) {
if ( getPointer( ).y( ) > barHeight ) {
double n = Math.floor( ( getPointer( ).y( ) - barHeight ) / itemHeight );
itemHover = ( int ) ( itemIndexOffset + n );
} else {
itemHover = -1;
}
}
public void updateItemIndexOffset( ) {
int m1 = items.size( ) > itemRange ? ( itemIndexOffset + itemRange ) : items.size( );
int n = ( m1 - items.size( ) );
if ( n >= 0 ) {
itemIndexOffset -= n;
}
}
}

Combine animations instead of blend?

I'm importing animations on a skinned mesh from a glTF created in Blender to THREE.js
I have two simultaneous animations that affect the translation of a bone. In Blender, these translations are summed, but in THREE.js they're averaged by weight.
For example, the animations are translate(2, 0, 0) and translate(4, 0, 0)
How do I get the AnimationMixer to result in (6, 0, 0) instead of (3, 0, 0)?
For my specific needs, I really only needed the values from the first and last frames (they're all 3 frame animations with the second being default values). So I pull the values from the keyframe tracks, and won't use the animation system at all.
//converts animations to values
fuction convertAnim( clips ){
var anims = [];
for ( i = 0; i < clips.length; i ++ ){
anims[i] = {name: "name", bone: []};
anims[i].name = clips[i].name;
for ( j = 0; j < clips[i].tracks.length; j++ ){
var val = clips[i].tracks[j].values
if ( clips[i].tracks[j].name.indexOf( 'position' ) > -1 ) {
anims[i].bone[j] = { name: "name", minTranslate: "min", maxTranslate: "max"};
anims[i].bone[j].name = clips[i].tracks[j].name;
anims[i].bone[j].minTranslate = new THREE.Vector3( val[0], val[1], val[3] );
anims[i].bone[j].maxTranslate = new THREE.Vector3( val[val.length - 3], val[val.length - 2], val[val.length - 1] );
}
else if ( clips[i].tracks[j].name.indexOf( 'scale' ) > -1 ) {
anims[i].bone[j] = { name: "name", minSize: "min", maxSize: "max"};
anims[i].bone[j].name = clips[i].tracks[j].name;
anims[i].bone[j].minSize = new THREE.Vector3( val[0], val[1], val[2] );
anims[i].bone[j].maxSize = new THREE.Vector3( val[val.length - 3], val[val.length - 2], val[val.length - 1] );
}
else if ( clips[i].tracks[j].name.indexOf( 'scale' ) > -1 ) {
anims[i].bone[j] = { name: "name", minRotation: "min", maxRotation: "max"};
anims[i].bone[j].name = clips[i].tracks[j].name;
anims[i].bone[j].minRotation = new THREE.Quaternion( val[0], val[1], val[2], val[3] );
anims[i].bone[j].maxRotation = new THREE.Quaternion( val[val.length -4], val[val.length - 3], val[val.length - 2], val[val.length - 1] );
}
}
}
return anims;
}

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;
}

HaxeFlixel animations not playing

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.

How to merge two rethinkdb documents using some function

I want to translate a merge function from the following JS code to us in RQL:
var d1 = {
del: {
1: {n: 1, v: 100, vFx:[100, 110]},
2: {n: 1, v: 100, vFx:[100, 110]}
}};
var d2 = {
del: {
2: {n: 1, v: 100, vFx:[100, 110]},
3: {n: 1, v: 100, vFx:[100, 110]}
}};
function merge(d1, d2) {
for(k in d2.del){
v = d2.del[k];
d1v = d1.del[k];
if(!d1v){
d1.del[k] = v;
} else{
d1v.n += v.n;
d1v.v += v.v;
for(var i = 0, _len = v.vFx.length; i < _len; i++)
d1v.vFx[i] += v.vFx[i];
}
}
};
// test
merge(d1, d2);
console.log(d1);
// GOAL
r.do(d1, d2, merge) // this of course doesn't work
My main problem is how to iterate through keys of a document? r.forEach requires me to make a save inside. My use case is that I want to use this merge function in update:
rqlexpr.update(merge(d1, r.row))
You can map over the keys of a document with keys, and construct an object with object. For example:
d1.merge(
r.object(
d2('del').keys().concatMap(function(key) {
return r.branch(
d1('del').hasField(key).not(),
[key, d2('del').getField(key)],
[key, d1('del').getField(key) + d2('del').getField(key)]
)
})
)
)

Resources