Cocos2d 2.1, file loading returns null - cocos2d-iphone

Here is my code. Worked in Cocos2d 2.0 and same code returns null in 2.1beta
const GLchar * fragmentSource = (GLchar*) [[NSString stringWithContentsOfFile:[CCFileUtils fullPathFromRelativePath:#"CSEGrass.fsh"] encoding:NSUTF8StringEncoding error:nil] UTF8String];
Already added CSEGrass.fsh to xcode target. Why returns null?

Related

Why does C++ node api for electron not allow for initialization of arraybuffers using external data?

I was recently developing a NodeJs module for electron using C++ and the Node addon C++ API.
I wanted to create an ArrayBuffer object containing the data of an image I read using c++ iostream functions like ifstream::read(). I allocated the buffer holding the image data using the "new char[]" operator and then tried to pass the pointer to the function Napi::ArrayBuffer::New(napi_env, void*, size_t) but when I try to run the electron application I get the following error:
[45256:1208/161314.044:ERROR:node_bindings.cc(149)] Fatal error in V8: v8_ArrayBuffer_NewBackingStore When the V8 Sandbox is enabled, ArrayBuffer backing stores must be allocated inside the sandbox address space. Please use an appropriate ArrayBuffer::Allocator to allocate these buffers, or disable the sandbox.
[45256:1208/161314.074:ERROR:crashpad_client_win.cc(844)] not connected
I have no idea of what it means nor did I find anything on the internet about fixing this issue.
Here is the code:
addon.cc:
Napi::ArrayBuffer loadImage(const Napi::CallbackInfo& info) {
std::ifstream image("img.jpg");
Napi::ArrayBuffer imageBuffer;
int bufferSize;
image.seekg(0, image.end);
bufferSize = image.tellg();
image.seekg(0, image.beg);
char *data = new char[bufferSize];
image.read(data, bufferSize);
imageBuffer = Napi::ArrayBuffer::New(info.Env(), (void*)data, bufferSize);
return imageBuffer;
}
addon.js:
const testAddon = require('./build/Release/testaddon.node')
const electron = require("electron")
const path = require('path')
const { ipcMain, BrowserWindow, app } = require('electron');
const createWindow = () => {
const win = new BrowserWindow({width: 800, height: 600, webPreferences: {
preload: path.join(__dirname, 'preload.js')
}, contextIsolation: true})
win.loadFile("test.html")
}
app.whenReady().then(() => {createWindow()})
var eddu = testAddon.loadImage();
Electron broke this in 21 as you noticed, there has been some discussion with them at https://github.com/electron/electron/issues/35801.
But the ultimate answer is that you can't do Napi::ArrayBuffer::New() with an existing pointer anymore in Electron. As you are already doing a copy into data you could instead do:
imageBuffer = Napi::ArrayBuffer::New(info.Env(), bufferSize);
image.read(imageBuffer.Data(), bufferSize);
Or in other cases where a copy is not being done then Napi::ArrayBuffer::Copy() could be used instead, or the upcoming Napi::ArrayBuffer::NewOrCopy() method.
Ref: https://github.com/nodejs/node-addon-api/blob/main/doc/array_buffer.md

ARC Objective-C delegation through a C++ abstract layer

I'm programming simple cross platform C++ layer (dylib) that gets implemented by Objective-C. The parts that are platform specific are included through platform macros.
The NSUserNotificationCenter requires the delegation pattern for handling specific actions, clicking on the notification for example. The issue I'm facing is that as soon as I execute send, the notification is sent but the instance unloads right after that. Thus the onclick notification action never gets called (didActivateNotification) instead it crashes for a bad pointer. How can I make this work?
Note:
SomeObjectiveC.mm is a class located in my Application. AppleUserNotificationManager.m is initialized by NotificationManager+apple.mm and both are located in my Dylib.
SomeObjectiveC.mm
Notification *notification = new Notification;
notification->setTitle("Foo bar notification");
notification->setMessage("Hello world!");
NotificationManager *notificationManager = new NotificationManager;
notificationManager->send(notification);
NotificationManager+apple.mm
#include "notificationManager+apple.hpp"
bool NotificationManager::send(Notification *notification)
{
AppleUserNotificationManager *notificationManager = [[AppleUserNotificationManager alloc] init];
NSString *title = [NSString stringWithUTF8String:notification->getTitle().c_str()];
NSString *message = [NSString stringWithUTF8String:notification->getMessage().c_str()];
if (notification->getSoundName().empty()) {
[notificationManager sendWithTitle:title andMessage:message];
}
NSString *soundName = [NSString stringWithUTF8String:notification->getSoundName().c_str()];
[notificationManager sendWithTitle:title andMessage:message andSound: soundName];
return true;
}
AppleUserNotificationManager.m
#import "AppleUserNotificationManager.h"
#implementation AppleUserNotificationManager
#synthesize userNotification;
- (id)init
{
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate: self];
userNotification = [[NSUserNotification alloc] init];
self = [super init];
return self;
}
/**
* #param NSUserNotificationCenter center
* #param NSUserNotification notification
*
* #return bool
*/
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification{
return YES;
}
/**
* #param NSUserNotificationCenter center
* #param NSUserNotification notification
*/
- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
{
NSString *notificationText = [notification informativeText];
NSString *urlRegEx = #"(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+";
NSPredicate *urlTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", urlRegEx];
if ([urlTest evaluateWithObject:notificationText]) {
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:notificationText]];
}
}
/**
* #param NSString title
* #param NSString message
* #param NSString soundName
*/
- (void)sendWithTitle:(NSString *)title andMessage:(NSString *)message andSound:(NSString *)soundName{
userNotification.title = title;
userNotification.informativeText = message;
userNotification.soundName = soundName;
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification: userNotification];
}
#end
Used self pointer before allocated?
Could below change fix the problem?
- (id)init
{
self = [super init];
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate: self];
userNotification = [[NSUserNotification alloc] init];
return self;
}

stringValue of NSDictionary objectForKey runtime error

So I have the following code that causes a runtime error in XCode
NSString* temp = [[param objectforkey#"firstParam"] stringValue];
int tempNum = [[param objectforkey#"secondParam"] intValue];
param loads from a plist. firstParam is as string, secondParam is a number
First line crashes the program.
Now what's interesting is it works if I do a hard caste i.e:
NSString* temp = (NSString*)[param objectforkey#"firstParam"];
int tempNum = [[param objectforkey#"secondParam"] intValue];
Just wondering why the id would have inconsistent implementation in that I have to use intValue to cast to int, but have to do hard cast to get NSString? Why not stringValue?
Your first call to objectForKey returns an object which is an NSString. NSString doesn't have a stringValue method which is why a runtime error is generated. It doesn't make sense to get the stringValue of something that is already a string.
The second call to objectForKey returns an NSNumber. NSNumber does have an intValue method so it doesn't cause an error.
In the second case you are changing the type of the returned value from NSNumber to int. In the first case the object returned is already an NSString and there is no point trying to get the stringValue of a string.
The call [param objectforkey#"firstParam"] DOES return a NSString, so there's no need to call stringValue. Furthermore, NSString does not have a method called "stringValue", so that's the source of your problem.
Just call this: NSString *temp = (NSString *)[param objectForKey:#"firstParam"];
Also note that the selector is objectForKey:, not objectforkey: (capitalization matters).
And, answering your question, NSNumber is a class, so any object is not an "int", but a NSNumber pointer. intValue returns an actual "int", as floatValue returns a "float" (NSNumber can represent any type of number). In the case of the NSString that's not necessary, because there is only one type of NSString (there is, though, a method for returning a const char *, and that would be used like char *string = [[param objectForKey:#"firstParam"] cString];... not very useful for Objective-C apps anyway).
Lets say you call a web service that returns JSON
Then you process data
NSDictionary *json_response = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
now you try something like this
NSString *name = [[object objectForKey:#"Name"] stringValue];
then you get the error....
As mttrb mentions you get the error because of stringValue, objectForKey default return value is String so a potential fix in this case would be:
NSString *name = [object objectForKey:#"Name"];
Hope this hints some one!
If you can not be sure that the returned value is a NSString you should do this:
id value = [param objectForKey#"firstParam"];
if ([value isKindOfClass:[NSString class]]) {
NSString *temp = (NSString *)id;
//Handle string
}
else {
//Handle other case
}
Completing the answer of #Torge, I add my solution to get always an NSString from objectForKey method:
NSObject * value = [param objectForKey#"firstParam"];
NSString *stringValue;
if ([value isKindOfClass:[NSString class]]) {
//Handle string
stringValue = (NSString *)value;
}
else if([value isKindOfClass:[NSNumber class]]){
//Handle NSNumber
stringValue = [((NSNumber *) value) stringValue];
}
else {
//Handle other case
}

cocos2d 1.1 sprite for retina 4 inch iPhone5

I use cocos2d 1.1, xCode 4.5 for my game's progect. I would like to recode my game for support the iPhone 5. But I faced with problem: cocos2d 1.1 can't detected sprite for retina 4 inch.
Default-568h#2x.png - work fine, but the game's sprites appears as *-hd.png.
It seems cocos2d 1.1 can detected just *-hd.png, however I added the sprites *-568h#2x.png.
Sorry for my English.
The solving of this problem is in CCFileUtils.m file as written below sergio.
I did the little changes in method +(NSString*) getDoubleResolutionImage:(NSString*)path
+(NSString*) getDoubleResolutionImage:(NSString*)path
{
#if CC_IS_RETINA_DISPLAY_SUPPORTED
if( CC_CONTENT_SCALE_FACTOR() == 2 )
{
NSString *pathWithoutExtension = [path stringByDeletingPathExtension];
NSString *name = [pathWithoutExtension lastPathComponent];
NSString *extension = [path pathExtension];
if( [extension isEqualToString:#"ccz"] || [extension isEqualToString:#"gz"] )
{
extension = [NSString stringWithFormat:#"%#.%#", [pathWithoutExtension pathExtension], extension];
pathWithoutExtension = [pathWithoutExtension stringByDeletingPathExtension];
}
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
if ([UIScreen mainScreen].scale == 2.f && screenHeight == 568.0f)
{
if( [name rangeOfString:CC_RETINA4_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) {
CCLOG(#"cocos2d: WARNING Filename(%#) already has the suffix %#. Using it.", name, CC_RETINA4_DISPLAY_FILENAME_SUFFIX);
return path;
}
NSString *retinaName = [pathWithoutExtension stringByAppendingString:CC_RETINA4_DISPLAY_FILENAME_SUFFIX];
retinaName = [retinaName stringByAppendingPathExtension:extension];
if( [__localFileManager fileExistsAtPath:retinaName] )
{
return retinaName;
}
}
if( [name rangeOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) {
CCLOG(#"cocos2d: WARNING Filename(%#) already has the suffix %#. Using it.", name, CC_RETINA_DISPLAY_FILENAME_SUFFIX);
return path;
}
NSString *retinaName = [pathWithoutExtension stringByAppendingString:CC_RETINA_DISPLAY_FILENAME_SUFFIX];
retinaName = [retinaName stringByAppendingPathExtension:extension];
if( [__localFileManager fileExistsAtPath:retinaName] )
{
return retinaName;
}
CCLOG(#"cocos2d: CCFileUtils: Warning HD file not found: %#", [retinaName lastPathComponent] );
}
#endif // CC_IS_RETINA_DISPLAY_SUPPORTED
return path;
}
and also add in file ccConfig.h
#ifndef CC_RETINA4_DISPLAY_FILENAME_SUFFIX
#define CC_RETINA4_DISPLAY_FILENAME_SUFFIX #"-568h#2x"
#endif
If someone have a notice, please write
As far as I know, there is no general support in Cocos2D 2.x for iPhone 5 -568h#2x images.
The only iPhone 5 specific support that was added to cocos2D 2.1 concerns the addition of a Default-568h#2x.png image to the Xcode template. Read the ChangeLog for details.
On the other hand, it is also true that in UIKit too there is no support for "-568h#2x images", so I don't think that cocos2D is going to add one.
On a more conceptual level, I understand that the general approach to supporting iPhone 5 resolution is not at the bitmap level (i.e., providing differently scaled images), rather at the layout level (i.e., changing the disposition or sizes of non-image UI elements). (If you think about it, we already have to manage x1 and x2 images, both for iPhone and iPad: this means 4 different versions for each image; adding another dimension to this would be crazy.)
If your app really does need using scaled images, then I guess you are on your own both when using UIKit and when using cocos2D.
On the bright side, if you give a look at CCFileUtils.h you can easily change it so that it supports the -568h#2x. If you want a discussion of this, have a look at this blog post which describes an analogous change but for the iPad 3. It might help you in building your own solution.
You can change suffix in ccConfig.h file
#ifndef CC_RETINA_DISPLAY_FILENAME_SUFFIX
#define CC_RETINA_DISPLAY_FILENAME_SUFFIX #"-hd"
#endif

How do you use a return value of true in Dart?

I get the following error when I try to execute the code below.
Uncaught TypeError: Object true has no method 'dartObjectLocalStorage$getter'
I started a Web Application in Dart Editor Version 0.1.0.201201150611 Build 3331. Here is the complete code for the lone dart file. The if statement that results in the error is commented below.
#import('dart:html');
class Test3D {
CanvasElement theCanvas;
WebGLRenderingContext gl;
static String vertexShaderSrc = """
attribute vec3 aVertexPosition;
void main(void) {
gl_Position = vec4(aVertexPosition, 1.0);
}
""";
Test3D() {
}
void run() {
write("Hello World!");
// Set up canvas
theCanvas = new Element.html("<canvas></canvas>");
theCanvas.width = 100;
theCanvas.height = 100;
document.body.nodes.add(theCanvas);
// Set up context
gl = theCanvas.getContext("experimental-webgl");
gl.clearColor(0.5, 0.5, 0.5, 1.0);
gl.clear(WebGLRenderingContext.COLOR_BUFFER_BIT);
WebGLShader vertexShader = gl.createShader(WebGLRenderingContext.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSrc);
gl.compileShader(vertexShader);
// Adding this line results in the error: Uncaught TypeError: Object true has no method 'dartObjectLocalStorage$getter
var wasSuccessful = gl.getShaderParameter(vertexShader, WebGLRenderingContext.COMPILE_STATUS);
}
void write(String message) {
// the HTML library defines a global "document" variable
document.query('#status').innerHTML = message;
}
}
void main() {
new Test3D().run();
}
I'm really keen on dart and would appreciate any help you could give me on this.
Here is the console output for the error:
Uncaught TypeError: Object true has no method 'dartObjectLocalStorage$getter'
htmlimpl0a8e4b$LevelDom$Dart.wrapObject$member
htmlimpl0a8e4b$WebGLRenderingContextWrappingImplementation$Dart.getShaderParameter$member
htmlimpl0a8e4b$WebGLRenderingContextWrappingImplementation$Dart.getShaderParameter$named
unnamedb54266$Test3D$Dart.run$member
unnamedb54266$Test3D$Dart.run$named
unnamedb54266$main$member
RunEntry.isolate$current
isolate$Isolate.run
isolate$IsolateEvent.process
isolate$doOneEventLoopIteration
next
isolate$doRunEventLoop
isolate$runEventLoop
RunEntry
(anonymous function)
The error indicates that somewhere in your code the field 'dartObjectLocalStorage' is accessed on the boolean true. The given code-snippet does not contain this identifier and is thus probably not responsible for the error.
It could be that the error-reporting gives the wrong line number (potentially even the wrong file).
To debug this:
try to find a reference to 'dartObjectLocalStorage' in your code.
try to find a reference to 'dartObjectLocalStorage$getter' in the generated code.
run on the VM or compile with a different compiler (frogc vs dartc).
good luck.
According to the documentation for WebGLRenderingContext the return type is Object, if you know the object is bool you can just use it as a bool or dynamic
var v=gl.getShaderParameter(vertexShader, WebGLRenderingContext.COMPILE_STATUS)
or more explicitly
var v=gl.getShaderParameter(vertexShader, WebGLRenderingContext.COMPILE_STATUS).dynamic
and then use it in your conditional statement. Also try compiling it with frogc rather than the build in JavaScript compiler, it usually results in better errors.