I am trying to investigate a memory leak problem and I found out that destructors in my library are not even called and I have the following code:
PPCamNET::Native::PpQueue::PpQueue(int capacity) : m_capacity(capacity), m_array(nullptr), m_head(0), m_tail(0)
{
// Quick fix for case when capacity is 1 (single snap)
// and Push function crashes on 1st frame
if (m_capacity == 1)
m_capacity = 2;
m_array = new FrameData[m_capacity];
m_pushes = 0;
m_pops = 0;
}
The above constructor's destructor should be called after PpQueue is destroyed, but it is not stopping at the break point.
PPCamNET::Native::PpQueue::~PpQueue()
{
delete[] m_array; //<==== here I set a break point
}
PPQueue instance is created by AcqCache constructor.
PPCamNET::Internal::AcqCache::AcqCache(AcqBuffer^ acqBuffer)
{
//m_stopWatchPush = Stopwatch::StartNew();
//m_stopWatchPop = Stopwatch::StartNew();
m_acqBuffer = acqBuffer;
m_cacheLock = gcnew Object();
m_processFrameRunning = true;
try
{
m_frameDataCache = new PpQueue(acqBuffer->BufferSize / 2 + 1);
AcqCache destructor removes m_frameDataCache, which is PpQueue.
PPCamNET::Internal::AcqCache::~AcqCache()
{
m_processFrameRunning = false;
delete m_frameDataCache; // <== here another break point but not called
delete[] m_frameInfoBuffer;
}
Finally the constructor of Acqusition creates an instance of m_acqCache with gcnew.
PPCamNET::Internal::Acquisition::Acquisition(AcqBuffer^ acqBuffer,
CameraSettings^ camSettings)
{
m_eofEvent = gcnew AutoResetEvent(false);
m_acqCache = gcnew AcqCache(acqBuffer);
I am puzzled why these destructors aren't called. Is this because GC didn't kick in to clear up m_acqCache causing other desructors not being called ?
Thanks,
GC will not call a destructor. The C++/CLI compiler translates destructors into IDisposable::Dispose() implementation, and has a different syntax (ClassName::!ClassName) which gets translated to Finalize.
C# wrongly confuses this issue by using the name "destructor" for the CLR Finalize function. Finalizers are not deterministic. The Dispose() function is not called automatically by GC. Not difficult once you know what's going on, but the terminology sure leads to confusion.
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. :)
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.
I didnt know how to exactly ask the question in the title but I can explain it here. So I have this class for pawns in my game.
And in my main program i call a bunch of instances of it with different names.
var z1:ZeleniPijun = new ZeleniPijun();
var z2:ZeleniPijun = new ZeleniPijun();
Basicly I have functions for movement and other variables that I use in my code in the class.
I'm making a multiplayer game and z1 and z2 would be pawns that I move around.
Until now I have used Switch and by knowing the ID of the player and the pawn that was clicked I moved them around the board. That means I have a switch for selecting a player and a switch inside that switch for selecting a pawn. And every time it goes trough the switch it goes to the same code but with a "different name".
For example if I roll a 4 for pawn number 1 it does
z1.movePawn(4);
z1.location += 4;
and other stuff that I need it to do
and if I roll a 3 for pawn number 2 it does
z2.movePawn(4);
z2.location += 4;
and other stuff that I need it to do
I have to copy the same code 16 times and just change the name from z1 to z2 to z3 etc...
Is there anyway I can make a function that would do that for me?
Something like this:
public function doStuff(pawnName:String, number:int):void{
pawnName.movePawn(number);
pawnName.location = number;
and other stuff that I need it to do
}
and then I can just give it the parameters I want 16 times instead of copying the same code everywhere.
send to the doStuff function the object that you want to do changes like
public function doStuff(theObj:ZeleniPijun ):void{
theObj.movePawn(number);
theObj.location = number;
and other stuff that I need it to do
}
if you have many objects, put them in a collection, like an array an iterate on it something like
foreach (obj in collection){
doStuff(obj);
}
this is just more or less pseudo-code, but you get the idea
You can use the object ZeleniPijun as parameter and call the method passing the instance you want.
// example creating multiples objects
var numObjs : uint = 5;
var objectsControl : Vector.<ZeleniPijun> = new Vector.<ZeleniPijun>(numObjs);
var zeleninPijun : ZeleniPijun;
for (var i : int = 0; i < numObjs; i++)
{
zeleninPijun = new ZeleniPijun();
objectsControl[i] = zeleninPijun;
}
// if you want to animate one object
doStuff(objectsControl[0], 4);
// if you want to animate them all
for each (var zeleninPijunObj : ZeleniPijun in objectsControl)
{
doStuff(zeleninPijunObj, 4);
}
function doStuff(pawnObj:ZeleniPijun, location:int):void
{
pawnObj.movePawn(location);
pawnObj.location = location;
}
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)