Neither adding a SKShapeNode nor adding a SKLabelNode to a SKScene appears to work? - skscene

Neither adding a SKShapeNode nor adding a SKLabelNode to a SKScene appears to work?
My gut guesses that I have a coordinate problem .. so here's the short code snippet which I have placed in my GameViewController class:
Note: I've added print statements below to debug.
FYI: I believe the values are wrong because they appear to be Frame coordinates, not Scene Coordinates. Frankly, I'm at a loss how to correct this error.
func addScoreLabelToScene(toScene: SKScene) {
if thisSceneName == "GameScene" {
let circleRadius = Double(100),
circleOffset = Double(30),
labelOffset = Double(10),
//
circlePosX = toScene.frame.size.width/2 - circleRadius - circleOffset,
labelPosX = circlePosX - labelOffset,
circlePosY = toScene.frame.size.height/2 + circleRadius + circleOffset,
labelPosY = circlePosY + labelOffset
// frame.size = 818, 1340
print("circlePosX = \(circlePosX)") // 279
print("circlePosY = \(circlePosY)") // 800
print("labelPosX = \(labelPosX)") // 269
print("labelPosY = \(labelPosY)") // 810
let circle = SKShapeNode(circleOfRadius: circleRadius)
circle.position = CGPoint(x: circlePosX, y: circlePosY)
circle.strokeColor = SKColor.red
circle.lineWidth = 2.0
circle.fillColor = SKColor.white
toScene.addChild(circle)
itsScoreLabel = SKLabelNode(fontNamed: "HelveticaNeue-Bold")
itsScoreLabel!.position = CGPoint(x: labelPosX, y: labelPosY)
itsScoreLabel!.text = "\(thisScore)"
itsScoreLabel!.fontSize = 20
itsScoreLabel!.fontColor = SKColor.blue
toScene.addChild(itsScoreLabel!)
}
} // addScoreLabelToScene
WRT to the above guess about a coordinate problem, I have hard-wired values for the PosX and PosY variables, but no success there.
In addition I have commented out both toScene.addChild() calls (one at a time) with no luck.
To complete the problem description, I have code elsewhere that adds several SKSpriteNodes with no problem.
So, what mammoth error am I committing?

As already commented above, I owe kelin above immeasurable thanks for motivating me to check my code again!
The central issue centers on specifying .zPosition = 10 or any very large number so the 2 Objects are not buried under everything.
So ... the NEW code which does it right:
func addScoreLabelToScene(toScene: SKScene) {
if thisSceneName == "GameScene" {
let circleRadius = Double(50), // lots of messing with #s involved
circleOffsetX = Double(25)
#if os(iOS)
let circleOffsetY = Double(105)
#elseif os(tvOS)
let circleOffsetY = Double(25)
#endif
// NR because we've centered the label within the circle.
// Nevertheless, as noted below, we still have to position it
// for horizontal + vertical alignment to take effect.
let labelOffsetX = Double(0),
labelOffsetY = Double(0),
//
circlePosX = toScene.frame.size.width/2 - circleRadius - circleOffsetX,
labelPosX = circlePosX - labelOffsetX,
circlePosY = toScene.frame.size.height/2 - circleRadius - circleOffsetY,
labelPosY = circlePosY - labelOffsetY
// added these print statements to debug:
// frame.size = 818, 1340
print("circlePosX = \(circlePosX)") // 334 = 818/2 - 50 - 25
print("circlePosY = \(circlePosY)") // 515 = 1340/2 - 50 - 105
print("labelPosX = \(labelPosX)") // 334 = 334 - 0
print("labelPosY = \(labelPosY)") // 515 = 515 - 0
let circle = SKShapeNode(circleOfRadius: circleRadius)
circle.zPosition = 10 // otherwise, the Object will be buried at the bottom
circle.position = CGPoint(x: circlePosX, y: circlePosY)
circle.strokeColor = SKColor.red
circle.lineWidth = 6.0
circle.fillColor = SKColor.white
toScene.addChild(circle)
itsScoreLabel = SKLabelNode(fontNamed: "HelveticaNeue-Bold")
itsScoreLabel!.zPosition = 10
// still gotta position it for alignment to take affect
itsScoreLabel!.position = CGPoint(x: labelPosX, y: labelPosY)
itsScoreLabel!.horizontalAlignmentMode = .center
itsScoreLabel!.verticalAlignmentMode = .center
itsScoreLabel!.text = "\(thisScore)"
itsScoreLabel!.fontSize = 30
itsScoreLabel!.fontColor = SKColor.blue
toScene.addChild(itsScoreLabel!)
}
} // addScoreLabelToScene

Related

Qt Quick MapPolyLine insertCoordinate

I have a PolyLine on my map and want to add a new co-ordinate to it when a user clicks between two existing points.
I can get the click event with:-
MouseArea {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
console.log('LINE');
}
}
But I cannot figure out how to work out the required index for insertCoordinate() as there does not appear to be a method to get the start/end vertices of the segment clicked. Is this possible?
I had a similar problem. Currently it cannot be done without writing a new Map object type. So I've changed approach completely and done the following:-
stopped using QtLocation for the map as it is too restrictive at present
integrated a WebKit control with Leaflet as the map provider in the browser HTML
used WebChannel and the WebSocketServer to communicate with the map via the javascript API
This has given me all the flexibility I need on the map as Leaflet is easy to configure and extend whilst allowing me to write the rest of the desktop app in Qt
I've revisited this project and found a way to do it without using Webkit. It is quite involved:-
1) use the click to get a coordinate
var mapCoord = gpxLine.mapToItem(mapView,mouseX,mouseY);
var coord = mapView.toCoordinate(Qt.point(mapCoord.x,mapCoord.y));
2) use this coordinate to iterate through the path and calculate the path line segment that it is closest to
float distance = 1000000;
float dx = 0;
int index = 0;
float x0 = coordinate.longitude(),
y0 = coordinate.latitude(),
x1y1x,
x1y1y,
x2y2x,
x2y2y;
double A,B,C,D,dot,len_sq,param,xx,yy,d_x,d_y;
for(int i = 0; i < trackpoints.count() - 1; i++){
//Distance from line algorithm https://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
x1y1x = trackpoints[i].latlon.longitude();
x1y1y = trackpoints[i].latlon.latitude();
x2y2x = trackpoints[i+1].latlon.longitude();
x2y2y = trackpoints[i+1].latlon.latitude();
A = x0 - x1y1x;
B = y0 - x1y1y;
C = x2y2x - x1y1x;
D = x2y2y - x1y1y;
dot = A * C + B * D;
len_sq = C * C + D * D;
param = dot /len_sq;
if(param < 0 || (x1y1x == x2y2x && x1y1y == x2y2y)){
xx = x1y1x;
yy = x1y1y;
} else if ( param > 1 ){
xx = x2y2x;
yy = x2y2y;
} else {
xx = x1y1x +param * C;
yy = x1y1y + param * D;
}
d_x = x0 - xx;
d_y = y0 - yy;
dx = sqrt(d_x * d_x + d_y * d_y);
if(dx < distance){
distance = dx;
index = i;
}
}
3) this gives me the index so I can now insert the coordinate at this index

Invalid index error in a for loop

I've been working in this code for a while, it's pretty simple, just recursive calculation. At the while loop, in the first line I got an index error. Funny thing is before I start using the if statement in loop my index was fine and I could compile it. My believe my problem is the lack of familiarity with the scilab way of programming.
///CONSTANTES////
roh_H20 = 1030.00 // [kg/m^3] Água Salgada
roh_ar = 1.22 // [kg/m^3]
g = 9.81 // [m/s^2]
V_elo = 0.00041 // [m^3]
V_boia = 0.00811 // [m^3]
V_lastro = 0.00811 // [m^3]
D_corda = 0.030 // [m]
A_corda = 1/4*%pi*D_corda**2
L_corda = 30 // [m]
roh_corda = 905 // [kg/m^3] poliester
V_corda = A_corda*L_corda // [m^3]
roh_elo = 952 // [kg/m^3] PE Alta Densidade
m_elo = 0.38817 // [kg]
m_boia = 1.5654 // [Kg]
m_lastro = 2.5 // [kg] CHUTE
m_corda = roh_corda*V_corda; // [kg]
Cd = 1.3 // coeficiente de arrasto placa plana FOX pg 396
N_elo = 7*24 // conjuntos a cada 1 metro
N_corda = 4 // A definir
N_boia = 7 // 2 primeiros conjuntos
N_lastro = 7 // 2 últimos conjuntos
/// PROBLEMA ESTATICO ////
M = N_elo*m_elo + N_boia*(m_boia + m_lastro) // FALTA CORDA
P = M*g
Emp = g*(N_boia*V_boia + N_elo*V_elo + N_lastro*V_lastro)*roh_H20;
printf("\n*****PROBLEMA ESTATICO*****\n")
printf("\nO Peso do conjunto eh: %f N\n", P)
printf("\nO Empuxo eh: %f N\n", Emp)
/// PROBLEMA DINÂMICO ///
A_vela = 0.03230 // [m^2] dado pelo SolidWorks
N_vela = 7
printf("\n*****PROBLEMA DINAMICO*****\n")
a = zeros(0,1e3)
a(1)= (Emp-P)/ M
printf("\na_0 = %f [m/s^2]\n", a(1))
t=0
v= zeros(0,1e3)
dy = zeros(0,1e3)
Fd = zeros(0,1e3)
for i=1:50
// if i == 1 then
// a(i)= (Emp-P)/ M
// else
// 1+1
// end
v(i+1) = v(i) + a(i)*t
dy(i+1) = dy(i)+v(i+1)*t+ a(i)*t*t/2.0
Fd(i+1) = 0.5*roh_H20*Cd*N_vela*A_vela*v(i+1)**2
if v(i+1) > 0 then
a(i+1) = (Emp - P - Fd(i+1))/ M;
elseif v(i+1) <= 0 then
a(i+1) = (Emp - P + Fd(i+1))/ M;
end,
t=t+0.05
end
x = linspace(0,t,int(i))
// Grafico velocidade/aceleração
clf(0)
scf(0)
subplot(2,1,1)
plot(x,a,'ro-')
xlabel("Tempo [s]")
ylabel("Acelaração [m/s^2]")
legend("aceleração")
subplot(2,1,2)
plot(x,v,'bs:')
xlabel("Tempo [s]")
ylabel("velocidade [m/s]")
legend("velocidade")
// Grafico forca/deslocamento
clf(1)
scf(1)
subplot(2,1,1)
plot(x,Fd,'r--d')
xlabel("Tempo [s]")
ylabel("Força [N]")
legend("Força Arrasto")
subplot(2,1,2)
plot(x,dy,'m--^')
xlabel("Tempo [s]")
ylabel("Descolcamento [m]")
legend("deslocamento")
Whenever you have index error, there are two things to do in the console:
Check the value of the index variable (just by entering its name)
Check the size(s) of any arrays involved (using the command size)
In this case, checking the size of a would show it's not what you expected it to be. Why? Because of this:
a = zeros(0,1e3)
v= zeros(0,1e3)
dy = zeros(0,1e3)
Fd = zeros(0,1e3)
The arguments of zeros are the height and width of a matrix. You are asking for height 0... this means empty matrix, since it has no rows. What you want is a row vector, which is a matrix with one row.
After fixing this you'll run into a problem with
x = linspace(0,t,int(i))
plot(x,a,'ro-')
because x and a are not of the same size.
To keep sizes consistent, you could do something like this:
imax = 50;
a = zeros(1,imax)
v= zeros(1,imax)
dy = zeros(1,imax)
Fd = zeros(1,imax)
and later for i=1:imax and x = linspace(0,t,imax).
This way you are not creating oversized arrays, but only arrays of the size you want, which can be adjusted by changing the value of imax.

Get physicsBody position when collide

I seem to have some problems with getting the position of a physicsBody.
I want to set the position of a physicsBody (bodyA) to the position of an other physicsBody (bodyB), when this one collides with a third one.
I tried using _bodyA.position = _bodyB.position; but this doesn't work.
The problem is, that the physicsBody I want to get the position of is moving around all the time. So I might need a method that checks the position of the physicsBody in every frame and when the physicsBody collides, the method returns the CGPoint.
This might be a simple task, but I can't figure it out. Thanks for help!
I did up a quick sample project for you to take a look at. You can fine tune the code to fit your exact needs but it will show you how to do what you asked.
Tap anywhere on the screen to launch the blue square into the red square. Once the two make contact, the green square's position will change to the red square.
Another alternative to the way I wrote the code is to have the sprites added to an array but that all depends on how your code is set up.
Side note - you cannot update a sprite's position in the didBeginContact: section because it will not work. That is why I created the CGPoint to store the position and update Object C during the next cycle in update:
Here is the code:
#import "MyScene.h"
typedef NS_OPTIONS(uint32_t, CNPhysicsCategory)
{
Category1 = 1 << 0,
Category2 = 1 << 1,
Category3 = 1 << 2,
};
#interface MyScene()<SKPhysicsContactDelegate>
#end
#implementation MyScene
{
SKSpriteNode *objectA;
SKSpriteNode *objectB;
SKSpriteNode *objectC;
CGPoint newPositionForObjectC;
}
-(id)initWithSize:(CGSize)size
{
if (self = [super initWithSize:size])
{
self.physicsWorld.contactDelegate = self;
objectA = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(30, 30)];
objectA.position = CGPointMake(110, 20);
objectA.name = #"objectA";
objectA.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:objectA.size];
objectA.physicsBody.categoryBitMask = Category1;
objectA.physicsBody.collisionBitMask = Category2;
objectA.physicsBody.contactTestBitMask = Category2;
objectA.physicsBody.affectedByGravity = NO;
[self addChild:objectA];
objectB = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(30, 30)];
objectB.position = CGPointMake(100, 200);
objectB.name = #"objectB";
objectB.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:objectB.size];
objectB.physicsBody.categoryBitMask = Category2;
objectB.physicsBody.collisionBitMask = Category1;
objectB.physicsBody.contactTestBitMask = Category1;
objectB.physicsBody.affectedByGravity = NO;
[self addChild:objectB];
objectC = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(30, 30)];
objectC.position = CGPointMake(250, 250);
objectC.name = #"objectC";
objectC.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:objectC.size];
objectC.physicsBody.categoryBitMask = Category3;
objectC.physicsBody.collisionBitMask = 0;
objectC.physicsBody.contactTestBitMask = 0;
objectC.physicsBody.affectedByGravity = NO;
[self addChild:objectC];
newPositionForObjectC = CGPointMake(0, 0);
}
return self;
}
- (void)didBeginContact:(SKPhysicsContact *)contact
{
uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
if (collision == (Category1 | Category2))
{
newPositionForObjectC = CGPointMake(contact.bodyA.node.position.x, contact.bodyA.node.position.y);
}
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[objectA.physicsBody applyImpulse:CGVectorMake(0, 5)];
}
-(void)update:(CFTimeInterval)currentTime
{
if(newPositionForObjectC.x > 0)
{
objectC.position = newPositionForObjectC;
newPositionForObjectC = CGPointMake(0, 0);
}
}
#end

Conditional Line Graph using Open Flash Charts

I am using Open Flash Charts v2. I have been trying to make Conditional line graph. But I couldn't find any straight forward way, example or any class for producing Conditional charts.
Example of Conditional Graph
So I thought to use some techniques to emulate conditional graph ,I made separate Line object for values above limit range and then this line is used to overlap the plotted line.
This techniques works some what ok ,but there are problems with it,
How to color or place the conditional colored line exactly above the limit.
Remove tooltip and dot from limit line.
Tooltip of conditional line(red) and plotted line(green) are both shown ,I only need tooltip of green line.
Conditional Line Graph Problem illustrated
Source Code: // C#
var chart = new OpenFlashChart.OpenFlashChart();
var data1 = new List<double?> { 1, 3, 4, 5, 2, 1, 6, 7 };//>4=
var overlap = new List<double?> { null, null, 4, 5, null, null, null, null };
var overlap2 = new List<double?> { null, null, null, null, null, null, 6, 7 };
var limitData = new List<double?> { 4, 4, 4, 4, 4, 4, 4, 4 };
var line1 = new Line();
line1.Values = data1;
//line1.HaloSize = 0;
line1.Width = 2;
line1.DotSize = 5;
line1.DotStyleType.Tip = "#x_label#<br>#val#";
line1.Colour = "#37c855";
line1.Tooltip = "#val#";
var overLine = new Line();
overLine.Values = overlap;
//overLine.HaloSize = 0;
overLine.Width = 2;
overLine.DotSize = 5;
overLine.DotStyleType.Tip = "#x_label#<br>#val#";
overLine.Colour = "#d81417";
overLine.Tooltip = "#val#";
var overLine2 = new Line();
overLine2.Values = overlap2;
//overLine2.HaloSize = 0;
overLine2.Width = 2;
overLine2.DotSize = 5;
//overLine2.DotStyleType.Tip = "#x_label#<br>#val#";
//overLine2.DotStyleType.Type = DotType.DOT;
overLine2.Colour = "#d81417";
overLine2.Tooltip = "#val#";
var limit = new Line();
limit.Values = limitData;
limit.Width = 2;
limit.Colour = "#ff0000";
limit.HaloSize = -1;
limit.DotSize = -1;
// limit.DotStyleType.Tip = "";
limit.DotStyleType.Type = null;
//limit.Tooltip = "";
chart.AddElement(line1);
chart.AddElement(overLine);
chart.AddElement(overLine2);
chart.AddElement(limit);
chart.Y_Legend = new Legend("Experiment");
chart.Title = new Title("Conditional Line Graph");
chart.Y_Axis.SetRange(0, 10);
chart.X_Axis.Labels.Color = "#e43456";
chart.X_Axis.Steps = 4;
chart.Tooltip = new ToolTip("#val#");
chart.Tooltip.Shadow = true;
chart.Tooltip.Colour = "#e43456";
chart.Tooltip.MouseStyle = ToolTipStyle.CLOSEST;
Response.Clear();
Response.CacheControl = "no-cache";
Response.Write(chart.ToPrettyString());
Response.End();
Note:
I have already downloaded the OFC (Open Flash Charts) source ,If I modify the OFC Line.as source than how would I be able to generate json for the changed graph ? ,b/c I'm currently using .Net library for the json generation for OFC charts,please do let me know this also.
Update:
I have modified the source code on the advice of David Mears I'm using FlashDevelop for ActionScript.
P.S: I'm open for ideas if another library can do this job.
If you don't mind a little rebuilding, you can get the source of OFC here and modify the Line.solid_line() method in open-flash-chart/charts/Line.as to do this fairly easily.
In order to set the extra chart details through JSON using the .NET library, you'll also have to modify OpenFlashChart/LineBase.cs to add alternative colour and boundary properties. I'm not hugely familiar with .NET, but based on the existing properties you might add something like this:
private double boundary;
private string altcolour;
[JsonProperty("boundary")]
public virtual double Boundary
{
set { this.boundary = value; }
get { return this.boundary; }
}
[JsonProperty("alt-colour")]
public virtual string AltColour
{
set { this.altcolour = value; }
get { return this.altcolour; }
}
Then I believe the following should work in Line.as:
public function solid_line(): void {
var first:Boolean = true;
var i:Number;
var tmp:Sprite;
var x:Number;
var y:Number;
var last_e:Element;
var ratio:Number;
for ( i=0; i < this.numChildren; i++ ) {
// Step through every child object.
tmp = this.getChildAt(i) as Sprite;
// Only include data Elements, ignoring extra children such as line masks.
if( tmp is Element )
{
var e:Element = tmp as Element;
if( first )
{
if (this.props.get('alt-colour') != Number.NEGATIVE_INFINITY) {
if (e._y >= this.props.get_colour('boundary'))
{
// Line starts below boundary, set alt line colour.
this.graphics.lineStyle( this.props.get_colour('width'), this.props.get_colour('alt-colour') );
}
else
{
// Line starts above boundary, set normal line colour.
this.graphics.lineStyle( this.props.get_colour('width'), this.props.get_colour('colour') );
}
}
// Move to the first point.
this.graphics.moveTo(e.x, e.y);
x = e.x;
y = e.y;
first = false;
}
else
{
if (this.props.get('alt-colour') != Number.NEGATIVE_INFINITY) {
if (last_e._y < this.props.get_colour('boundary') && e._y >= this.props.get_colour('boundary'))
{
// Line passes below boundary. Draw first section and switch to alt colour.
ratio = (this.props.get_colour('boundary') - last_e._y) / (e._y - last_e._y);
this.graphics.lineTo(last_e.x + (e.x - last_e.x) * ratio, last_e.y + (e.y - last_e.y) * ratio);
this.graphics.lineStyle( this.props.get_colour('width'), this.props.get_colour('alt-colour') );
}
else if (last_e._y >= this.props.get_colour('boundary') && e._y < this.props.get_colour('boundary'))
{
// Line passes above boundary. Draw first section and switch to normal colour.
ratio = (this.props.get_colour('boundary') - last_e._y) / (e._y - last_e._y);
this.graphics.lineTo(last_e.x + (e.x - last_e.x) * ratio, last_e.y + (e.y - last_e.y) * ratio);
this.graphics.lineStyle( this.props.get_colour('width'), this.props.get_colour('colour') );
}
}
// Draw a line to the next point.
this.graphics.lineTo(e.x, e.y);
}
last_e = e;
}
}
if ( this.props.get('loop') ) {
// close the line loop (radar charts)
this.graphics.lineTo(x, y);
}
}
With the new open-flash-chart.swf, you should be able to just set your new properties on line1:
line1.Boundary = 4;
line1.AltColour = "#d81417";

mapping rect in small image to larger image (in order to do a copyPixels operation)

this is (I think) a relatively simple math question but I've spent a day banging my head against it and have only the dents and no solution...
I'm coding in actionscript 3 - the functionality is:
large image loaded at runtime. The bitmapData is stored and a smaller version is created to display on the available screen area (I may end up just scaling the large image since it is in memory anyway).
The user can create a rectangle hotspot on the smaller image (the functionality will be more complex: multiple rects with transparency: example a donut shape with hole, etc)
3 When the user clicks on the hotspot, the rect of the hotspot is mapped to the larger image and a new bitmap "callout" is created, using the larger bitmap data. The reason for this is so the "callout" will be better quality than just scaling up the area of the hotspot.
The image below shows where I am at so far- the blue rect is the clicked hotspot. In the upper left is the "callout" - copied from the larger image. I have the aspect ratio right but I am not mapping to the larger image correctly.
Ugly code below... Sorry this post is so long - I just figured I ought to provide as much info as possible. Thanks for any tips!
--trace of my data values
*source BitmapDada 1152 864
scaled to rect 800 600
scaled BitmapData 800 600
selection BitmapData 58 56
scaled selection 83 80
ratio 1.44
before (x=544, y=237, w=58, h=56)
(x=544, y=237, w=225.04, h=217.28)
*
Image here: http://i795.photobucket.com/albums/yy237/skinnyTOD/exampleST.jpg
public function onExpandCallout(event:MouseEvent):void{
if (maskBitmapData.getPixel32(event.localX, event.localY) != 0){
var maskClone:BitmapData = maskBitmapData.clone();
//amount to scale callout - this will vary/can be changed by user
var scale:Number =150 //scale percentage
var normalizedScale :Number = scale/=100;
var w:Number = maskBitmapData.width*normalizedScale;
var h:Number = maskBitmapData.height*normalizedScale;
var ratio:Number = (sourceBD.width /targetRect.width);
//creat bmpd of the scaled size to copy source into
var scaledBitmapData:BitmapData = new BitmapData(maskBitmapData.width * ratio, maskBitmapData.height * ratio, true, 0xFFFFFFFF);
trace("source BitmapDada " + sourceBD.width, sourceBD.height);
trace("scaled to rect " + targetRect.width, targetRect.height);
trace("scaled BitmapData", bkgnImageSprite.width, bkgnImageSprite.height);
trace("selection BitmapData", maskBitmapData.width, maskBitmapData.height);
trace("scaled selection", scaledBitmapData.width, scaledBitmapData.height);
trace("ratio", ratio);
var scaledBitmap:Bitmap = new Bitmap(scaledBitmapData);
var scaleW:Number = sourceBD.width / scaledBitmapData.width;
var scaleH:Number = sourceBD.height / scaledBitmapData.height;
var scaleMatrix:Matrix = new Matrix();
scaleMatrix.scale(ratio,ratio);
var sRect:Rectangle = maskSprite.getBounds(bkgnImageSprite);
var sR:Rectangle = sRect.clone();
var ss:Sprite = new Sprite();
ss.graphics.lineStyle(8, 0x0000FF);
//ss.graphics.beginFill(0x000000, 1);
ss.graphics.drawRect(sRect.x, sRect.y, sRect.width, sRect.height);
//ss.graphics.endFill();
this.addChild(ss);
trace("before " + sRect);
w = uint(sRect.width * scaleW);
h = uint(sRect.height * scaleH);
sRect.inflate(maskBitmapData.width * ratio, maskBitmapData.height * ratio);
sRect.offset(maskBitmapData.width * ratio, maskBitmapData.height * ratio);
trace(sRect);
scaledBitmapData.copyPixels(sourceBD, sRect, new Point());
addChild(scaledBitmap);
scaledBitmap.x = offsetPt.x;
scaledBitmap.y = offsetPt.y;
}
}
Thanks!
public function onExpandCallout(event:MouseEvent):void{
// TODO: build this on startup or only on click? Speed vs memory
if (calloutState == true) return;
if (maskBitmapData.getPixel32(event.localX, event.localY) != 0){
calloutState = true;
//create bitmap from source using scaled selection rect
var ratio:Number = (sourceBMD.width /targetRect.width);
var sRect:Rectangle = hotSpotSprite.getBounds(bkgnImageSprite);
var destRect:Rectangle = new Rectangle(sRect.x * ratio, sRect.y * ratio, sRect.width * ratio, sRect.height * ratio);
calloutBitmapData = new BitmapData(destRect.width, destRect.height, true, 0xFFFFFFFF);
calloutBitmap = new Bitmap(calloutBitmapData);
//-- scale alpha mask
var scaledMaskBitmapData:BitmapData = new BitmapData(destRect.width, destRect.height, true, 0x00000000);
var maskScale:Number = scaledMaskBitmapData.width / maskBitmapData.width;
var mMatrix:Matrix = new Matrix(maskScale, 0, 0, maskScale);
scaledMaskBitmapData.draw(maskBitmapData,mMatrix,null,null,null, false);
// copy source with scaled alpha
calloutBitmapData.copyPixels(sourceBMD, destRect, new Point(), scaledMaskBitmapData, new Point());
scaledMaskBitmapData = null;
// apply filter to bitmap
var myDropShadowFilter:DropShadowFilter = new DropShadowFilter();
myDropShadowFilter.distance = 12;
myDropShadowFilter.alpha = .3
myDropShadowFilter.strength = 1;
myDropShadowFilter.blurX = 8;
myDropShadowFilter.blurY = 8;
calloutBitmap.filters = [myDropShadowFilter];
//place on screen
calloutSprite = new Sprite();
calloutSprite.addChild(calloutBitmap)
calloutSprite.x = offsetPt.x;
calloutSprite.y = offsetPt.y;
// ADD TO PARENT DisplayContainer
calloutLayer.addChild(calloutSprite);
// calloutSprite.scaleX = 2;
// calloutSprite.scaleY = 2;
calloutSprite.doubleClickEnabled = true;
calloutSprite.addEventListener(MouseEvent.DOUBLE_CLICK, onCollapseCallout);
calloutSprite.addEventListener(MouseEvent.MOUSE_DOWN, onStartDrag);
calloutSprite.addEventListener(MouseEvent.MOUSE_UP, onStopDrag);
}
}

Resources