Load/init Button with in memory imagery like Texture2D - cocos2d-x

I can only find methods to create Button:s from disk-based image files.
How would I set/change a button's normal/highlighted states from in-memory data like Texture2D, Image etc?
Cocos2D-x v3.5

Update 20160408:
I Googled this again, and Google suggested this page... and I have to thank my past self :-)
This time I wrote a handy tool function:
void Mjcocoshelper::rendernodetospriteframecache(Node* node, std::string nameincache) {
const Size SIZE = node->getBoundingBox().size;
auto render = RenderTexture::create(SIZE.width, SIZE.height);
render->begin();
const Vec2 POS_BEFORE = node->getPosition();
const bool IGNORE_BEFORE = node->isIgnoreAnchorPointForPosition();
const float SCALEY_BEFORE = node->getScaleY();
node->ignoreAnchorPointForPosition(false);
node->setPosition(SIZE.width * 0.5f, SIZE.height * 0.5f);
node->setScaleY(-1.0f); // Or it gets upside down?
node->visit();
node->ignoreAnchorPointForPosition(IGNORE_BEFORE);
node->setPosition(POS_BEFORE);
node->setScaleY(SCALEY_BEFORE);
render->end();
auto spriteNew = render->getSprite();
Texture2D* texture2d = spriteNew->getTexture();
SpriteFrame* spriteframeOff = SpriteFrame::createWithTexture(texture2d, Rect(0, 0, texture2d->getContentSize().width, texture2d->getContentSize().height));
SpriteFrameCache::getInstance()->addSpriteFrame(spriteframeOff, nameincache);
}
Old:
I figured out this kinda neat workaround:
std::string framenameOff;
{
Texture2D* texture2d = mjpromobuttonx.textureOff();
SpriteFrame* spriteframeOff = SpriteFrame::createWithTexture(texture2d, Rect(0, 0, texture2d->getContentSize().width, texture2d->getContentSize().height));
framenameOff = "autobutton_off_" + std::to_string(++buttonsaddedtocacheoff);
SpriteFrameCache::getInstance()->addSpriteFrame(spriteframeOff, framenameOff);
}
std::string framenameOn;
{
Texture2D* texture2d = mjpromobuttonx.textureOff();
SpriteFrame* spriteframeOn = SpriteFrame::createWithTexture(texture2d, Rect(0, 0, texture2d->getContentSize().width, texture2d->getContentSize().height));
framenameOn = "autobutton_on_" + std::to_string(++buttonsaddedtocacheon);
SpriteFrameCache::getInstance()->addSpriteFrame(spriteframeOn, framenameOn);
}
Button* item = Button::create(framenameOff, framenameOn, framenameOff, TextureResType::PLIST);
So what it does, it adds spriteframes on the fly to the sprite frame cache. We have to make sure that the names we store them with don't overwrite anything else, and we also have to keep creating new names for each image we add to the cache. On some extreme sad occasion maybe this would overwrite some existing image, so I'll give this some more thouhght... maybe... sometime...
Bonus:
I did have a ObjC framework I created earlier that fetches images from a remote server... um for now I reused it, and also needed to convert the UIImage:s the framework ended up with to something I could pass to C++ and then Cocos2D-x... so I used this, it works pretty well:
Texture2D* getTexture2DFromUIImage(UIImage *photo) {
#warning TODO: Make use of this baby later? Does it work? Do we need to free after malloc?
// https://stackoverflow.com/a/15134000/129202
Image *imf = new Image();
NSData *imgData = UIImagePNGRepresentation(photo);
NSUInteger len = [imgData length];
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [imgData bytes], len);
imf->initWithImageData(byteData,imgData.length);
imf->autorelease();
Texture2D* pTexture = new Texture2D();
pTexture->initWithImage(imf);
pTexture->autorelease();
return pTexture;
}
Now I'm just guessing that the malloc in that function should really have a free somewhere after it... but that's another issue.

Related

How does a computer resize an image?

Image resizing is nearly universal in any GUI framework. In fact, one of the first things you learn when starting out in web development is how to scale images using CSS or HTML's img attributes. But how does this work?
When I tell the computer to scale a 500x500 img to 100x50, or the reverse, how does the computer know which pixels to draw from the original image? Lastly, is it reasonably easy for me to write my own "image transformer" in another programming language without significant drops in performance?
Based on a bit of research, I can conclude that most web browser will use nearest neighbor or linear interpolation for image resizing. I've written a concept nearest neighbor algorithm that successfully resizes images, albeit VERY SLOWLY.
using System;
using System.Drawing;
using System.Timers;
namespace Image_Resize
{
class ImageResizer
{
public static Image Resize(Image baseImage, int newHeight, int newWidth)
{
var baseBitmap = new Bitmap(baseImage);
int baseHeight = baseBitmap.Height;
int baseWidth = baseBitmap.Width;
//Nearest neighbor interpolation converts pixels in the resized image to pixels closest to the old image. We have a 2x2 image, and want to make it a 9x9.
//Step 1. Take a 9x9 image and shrink it back to old value. To do this, divide the new width by old width (i.e. 9/2 = 4.5)
float widthRatio = (float)baseWidth/newWidth;
float heightRatio = (float)baseHeight/newHeight;
//Step 2. Perform an integer comparison for each pixel in old I believe. If we have a pixel in the new located at (4,5), then the proportional will be
//(.8888, 1.11111) which SHOULD GO DOWN to (0,1) coordinates on a 2x2. Seems counter intuitive, but imagining a 2x2 grid, (4.5) is on the left-bottom coordinate
//so it makes sense the to be on the (0,1) pixel.
var watch = new System.Diagnostics.Stopwatch();
watch.Start();
Bitmap resized = new Bitmap(newWidth, newHeight);
int oldX = 0; int oldY = 0;
for (int i = 0; i < newWidth; i++)
{
oldX = (int)(i*widthRatio);
for (int j = 0; j < newHeight; j++)
{
oldY = (int)(j*heightRatio);
Color newColor = baseBitmap.GetPixel(oldX,oldY);
resized.SetPixel(i,j, newColor);
}
}
//This works, but is 100x slower than standard library methods due to GetPixel() and SetPixel() methods. The average time to set a 1920x1080 image is a second.
watch.Stop();
Console.WriteLine("Resizing the image took " + watch.Elapsed.TotalMilliseconds + "ms.");
return resized;
}
}
class Program
{
static void Main(string[] args)
{
var img = Image.FromFile(#"C:\Users\kpsin\Pictures\codeimage.jpg");
img = ImageResizer.Resize(img, 1000, 1500);
img.Save(#"C:\Users\kpsin\Pictures\codeimage1.jpg");
}
}
}
I do hope that someone else can come along and provide either a) a faster algorithm for nearest neighbor because I'm overlooking something silly, or b) another way that image scalers work that I'm not aware of. Otherwise, question... answered?

Linking buttons to imported information from csv file

I would like to ask some help turning this representation into something more interactive. Im working with Processsing latest version. The main idea is I have a table in excel, I imported it into processsing. So far so good. Displayed the values as bubbles. My problem is that would like to create buttons to See further details from each bubble. So, click a button A, the corresponding bubbleA would light up and display its specific value, according to the imported table. I dont know how to connect the button to each bubble, neither how to turn the bubble to its original state once the button is pressed again.
I`m not from the programming field, I just manage to get this far with info that I have found online, so the code must be pretty messed up. I was trying to use the libraries from Processing but I cant really understand how the controlP5 works.. I asssume the structure is way more advanced than what I can handle now.
So, if anyone can help me, I would appreciate it very much.
Table B_A_table;
//Bubble[] bubbles = new Bubble[29];
ArrayList<Bubble> bubbles = new ArrayList<Bubble>();
float scale = 3;
int c_verdeClaro = color(182,189,149);
import controlP5.*;
ControlP5 cp5;
PFont font;
PFont font1;
void setup() {
size(1000, 1000);
colorMode(HSB,255);
loadData();
font = createFont("Verdana", 18);
font1 = createFont("Verdana Bold", 18);
//font = loadFont("Arial-Black-48.vlw");
//BEGIN TEST
cp5 = new ControlP5(this);
noStroke();
smooth();
//TEST
cp5 = new ControlP5(this);
ButtonBar b = cp5.addButtonBar("bar")
.setPosition(500, 0)
.setSize(400, 20)
.addItems(split("Man Woman 20s 30s 40s 50s µµ½É±Ç"," "))
;
println(b.getItem("Man"));
b.changeItem("a","text","first");
b.changeItem("b","text","second");
b.changeItem("c","text","third");
b.onMove(new CallbackListener(){
public void controlEvent(CallbackEvent ev) {
ButtonBar bar = (ButtonBar)ev.getController();
println("hello ",bar.hover());
}
});
//WND TEST
}
void draw() {
// Display all bubbles
background(0);
Graph_Bike_Aware_Experience_Sim();
//Graph_Bike_Uso_Satisf();
pushMatrix();
translate(400,500);
for (Bubble bubble : bubbles){
bubble.display();
}
popMatrix();
}
void loadData() {
// "header" indicates the file has header row. The size of the array
// is then determined by the number of rows in the table.
B_A_table = loadTable("BikeAwareExpr_Nao.csv", "header");
for (int i = 0; i<B_A_table.getRowCount(); i++) {
// Iterate over all the rows in a table.
TableRow row = B_A_table.getRow(i);
// Access the fields via their column name (or index).
float x = row.getFloat("awareness_x")*scale;
float y = row.getFloat("experi")*scale;
float d = row.getFloat("awareness_x")*0.2;
String n = row.getString("Awareness_Bike");
Float id = row.getFloat("ID");
// Make a Bubble object out of the data from each row.
bubbles.add(new Bubble(x, y, d, n,id));
//bubbles[i] = new Bubble(x, y, d, n);
}
}
// This simple Bubble class draws a circle to the window
// and displays a text label when the mouse hovers.
class Bubble {
float x, y;
float diameter;
String name;
Float id;
// Create the Bubble
Bubble(float tempX, float tempY, float tempD, String s, Float id) {
x = tempX;
y = tempY;
diameter = tempD;
name = s;
}
// Display the Bubble
void display() {
stroke(220);
strokeWeight(1);
noFill();
ellipse(x, y, diameter, diameter);
fill(200);
textFont(font,15);
textAlign(CENTER);
text(name, x,y);
}
}
void Graph_Bike_Aware_Experience_Sim(){
pushMatrix();
int tam_table = B_A_table.getRowCount();
translate(400,500);
stroke(150);
strokeWeight(1);
line( - 100 *scale, 0*scale, + 100*scale, 0*scale);
line(0*scale, - 100*scale, 0*scale, + 100*scale);
//fill(c_verdeClaro);
noStroke();
fill(255);
textFont(font,13);
text("Experience", 40 , -97*scale);
text("Awareness", -89*scale, -10);
fill(50);
//textFont(Arial-Black-48, 32);
text("0", 10,15);
pushMatrix();
fill(0);
textFont(font1,30 );
text("IDEAL", 80*scale , -120*scale);
fill(70);
textFont(font1,25 );
text("Bicycle", 0 , -110*scale);
popMatrix();
popMatrix();
}
/*void Graph_Bike_Uso_Satisf(){
pushMatrix();
int tam_table = B_A_table.getRowCount();
translate(900,400);
stroke(150);
strokeWeight(1);
line( - 100 *scale, 0*scale, + 100*scale, 0*scale);
line(0*scale, - 100*scale, 0*scale, + 100*scale);
//fill(c_verdeClaro);
noStroke();
c_verdeClaro_grad();
c_verdeEscuro_grad();
c_Vermelho_grad();
fill(255);
text("Experience", 40 , -97*scale);
text("Awareness", -89*scale, -10);
fill(0);
//textFont(Arial-Black-48, 32);
text("word", 10, 50);
text("IDEAL", 97*scale , -97*scale);
popMatrix();
}
*/
To handle this without Object Oriented Programing, or 'OOP' is a waste of time and code.
But relax OOP also referred to as "Objects" or " Classes". It is not that hard to get. In fact it is simple to learn, I mean, the basic stuff. And it makes things very easy.
In your case, you need to build an object to represent your data. Then you create several of them, populate with data, and all will be hold together. Kind of knowing it own business.
The usual example is
Class car
has those properties
color
plate
Then you can say:
Make a Blue, 3231 car!
Make a Red, 3001 car!
and so on...
When you need it you can ask, Blue car what's your plate, and it will know.
They can also have kind of "behaviours" known as functions or methods. Those do things, so you could say: "Red, turn right", or "Bubble, show me your data!" and they will OBEY you. :)
There is no point in trying to teach this hear though. There are TONs of great tutorials around. Use Duck Duck Go :) or google if you like.
This one here are from Processing's tutorials section itself. Great ones to begin with. :)

Ask how to give jProgressBar for my iteration

I want to ask how to give jProgressBar in my code. i used netbeans interface. progressBar will end after it reach maximum_iteration.
jProgressBar already in other class. how can i fix it? Thank you. Please help.
train() is placed in other class.
public void train(){
for(int iteration=0; iteration<this.max_iteration; iteration++){
//int percent = (iteration/this.max_iteration) * 100;
//cs.jProgressBar1.setValue(percent);
for(int index=0; index<this.hms; index++){
Node[] newChord = {};
double random = Math.random();
/*process HS*/
if(this.original_chord != null){
// ensure the fist note of the new chord is not altered
newChord[0].notes = new int[first_chord_notes.length];
for(int j=0; j<first_chord_notes.length; j++){
newChord[0].notes[j] = first_chord_notes[j];
}
}
// evaluate new chord and substitute the worst one in hs if new chord is better
double newFitness = this.nodeListFitness(this.original_chord, newChord);
int worstIndex = this.worst_index();
double worstFitness = this.fitness[worstIndex];
if(newFitness > worstFitness){
this.hm[worstIndex] = newChord;
this.fitness[worstIndex] = newFitness;
}
}
System.out.println("Harmony Memory " + (iteration+1));
this.debug();
System.out.println("");
//JProgressBar jProgressBar1 = new JProgressBar();
//cs.jProgressBar1.setValue(iteration);
//cs.jProgressBar1.setEnabled(true);
}
}
I'm not sure at 100% but a Swing Component can be updated only inside the EventDispatcherThread, which is the Thread that run the GUI. For this reason, it will probably be better that you call the method train() inside you GUI, so it run into the EDT. Also, I can't understand why do you call the constructor of the JProgessBar, if you say that it is already in other class, probably the other class (I image it is the GUI) has already created a new instance of the progress bar.

Few basics in cocos2d-x v3 Windows

I have some basic questions about some Problems in cocos2d-x v3.
1.) when I create sprites like that:
cocos2d::Sprite *sprite1 = cocos2d::Sprite::create("test.png");
auto sprite2 = cocos2d::Sprite::create("test.png");
How I have to to erease them proplery? Should I use autorelease (it crashes when I use it after create it)? Can I for both variants just use:
sprite1->removeFromParentAndCleanup(true);
sprite2->removeFromParentAndCleanup(true);
2.) When I want an Animation have active in my HelloWorldScene, so that i can use it when i want, how can I do it? I tried something like that:
void HelloWorld::runAnimationWalk() {
auto spritebatch = cocos2d::SpriteBatchNode::create("robo.png");
auto cache = cocos2d::SpriteFrameCache::getInstance();
cache->addSpriteFramesWithFile("robo.plist");
//spritebatch->addChild(worker);
Vector<SpriteFrame *> animFrames(5);
char str[100] = {0};
for(int i = 1; i <= 5; i++)
{
sprintf(str, "robot%i.png", i);
cocos2d::SpriteFrame* frame = cache->getSpriteFrameByName( str );
animFrames.pushBack(frame);
}
auto animWalk = cocos2d::Animation::createWithSpriteFrames(animFrames, 0.1f);
vector<Worker>::iterator it = workerVector.begin();
for(int k = 0; k<workerVector.size();k++) {
if(it->getType() == 1)
it->getWorker()->runAction(RepeatForever::create(Animate::create(animWalk)));
it++;
}
}
That works, but i have to call the function always after I want to change the animation. I tried to save the spritebatch, cache etc... global, but the animation dissaperars after a few time.
Answer 1) Yes. This is a full scenario:
//Create
Sprite *sprite1 = cocos2d::Sprite::create("test.png");
this->addChild(sprite1);
// Deleter Later
sprite1->removeFromParent();
Answer 2) You can create an animation ( Animation* ) and run it on any sprite.
some note:
If you want the animation play again and again, you can make a infinite version of your animation with RepeatForever::create(YourAnimation).
If you want to create the animation but use(display) it later. you can create your Animation* and retain() it until you run it on some target(sprite). (don't forget ro release it when running on target)

Overflow on PivotPage WP8

public MainPage()
{
InitializeComponent();
PivotMain.Items.Clear();
for (int k = 1; k < 157; k++)
{
p = new PivotItem();
Image i = new Image();
i.Source = new BitmapImage(new Uri(#"Resources/Images/"+k+".jpg", UriKind.Relative));
p.Margin = new Thickness(0, -100, 0, -2);
p.Content = i;
p.Header = k.ToString()+". ";
p.Name = "page" + k;
PivotMain.Items.Add(p);
}
But looks like it has its own limitations? No mater how I load pivot items ( Databinding Vs xml, runtime in code ). It gives out of memory exception if items are more then 40.
How can i fix it?
It is recommended not to have more than 5 pivot items, memory consumption may by one of the reasons. You can try loading the image on each pivot tab when the tab is selected and setting images on all the other tabs to null (or removing from the tab), this may help.
If you want to built something like a gallery, I recommend the SlideView control from Telerik, it works fine with large datasets.