mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
More android support
This commit is contained in:
parent
0631441b20
commit
bc85e1a4f2
49
panda/src/android/NativeIStream.java
Executable file
49
panda/src/android/NativeIStream.java
Executable file
@ -0,0 +1,49 @@
|
||||
// Filename: NativeIStream.java
|
||||
// Created by: rdb (22Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
package org.panda3d.android;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : NativeIStream
|
||||
// Description : An implementation of InputStream that gets its
|
||||
// data from a C++ istream pointer, passed as long.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
public class NativeIStream extends InputStream {
|
||||
private long streamPtr = 0;
|
||||
|
||||
public NativeIStream(long ptr) {
|
||||
streamPtr = ptr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() {
|
||||
return nativeGet(streamPtr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] buffer, int offset, int length) {
|
||||
return nativeRead(streamPtr, buffer, offset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) {
|
||||
return nativeIgnore(streamPtr, n);
|
||||
}
|
||||
|
||||
private static native int nativeGet(long ptr);
|
||||
private static native int nativeRead(long ptr, byte[] buffer, int offset, int length);
|
||||
private static native long nativeIgnore(long ptr, long offset);
|
||||
}
|
58
panda/src/android/PandaActivity.java
Executable file
58
panda/src/android/PandaActivity.java
Executable file
@ -0,0 +1,58 @@
|
||||
// Filename: PandaActivity.java
|
||||
// Created by: rdb (22Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
package org.panda3d.android;
|
||||
|
||||
import android.app.NativeActivity;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import org.panda3d.android.NativeIStream;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PandaActivity
|
||||
// Description : The entry point for a Panda-based activity. Loads
|
||||
// the Panda libraries and also provides some utility
|
||||
// functions.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
public class PandaActivity extends NativeActivity {
|
||||
protected static BitmapFactory.Options readBitmapSize(long istreamPtr) {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
options.inScaled = false;
|
||||
NativeIStream stream = new NativeIStream(istreamPtr);
|
||||
BitmapFactory.decodeStream(stream, null, options);
|
||||
return options;
|
||||
}
|
||||
|
||||
protected static Bitmap readBitmap(long istreamPtr, int sampleSize) {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
//options.inPreferredConfig = Bitmap.Config.RGBA_8888;
|
||||
options.inScaled = false;
|
||||
options.inSampleSize = sampleSize;
|
||||
NativeIStream stream = new NativeIStream(istreamPtr);
|
||||
return BitmapFactory.decodeStream(stream, null, options);
|
||||
}
|
||||
|
||||
static {
|
||||
System.loadLibrary("gnustl_shared");
|
||||
System.loadLibrary("p3dtool");
|
||||
System.loadLibrary("p3dtoolconfig");
|
||||
System.loadLibrary("pandaexpress");
|
||||
System.loadLibrary("panda");
|
||||
System.loadLibrary("p3android");
|
||||
System.loadLibrary("p3framework");
|
||||
System.loadLibrary("pandaegg");
|
||||
System.loadLibrary("pandagles");
|
||||
}
|
||||
}
|
76
panda/src/android/android_main.cxx
Normal file
76
panda/src/android/android_main.cxx
Normal file
@ -0,0 +1,76 @@
|
||||
// Filename: android_main.cxx
|
||||
// Created by: rdb (12Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_android.h"
|
||||
#include "config_util.h"
|
||||
#include "virtualFileMountAndroidAsset.h"
|
||||
#include "virtualFileSystem.h"
|
||||
|
||||
#include "config_display.h"
|
||||
//#define OPENGLES_1
|
||||
//#include "config_androiddisplay.h"
|
||||
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
//struct android_app* panda_android_app = NULL;
|
||||
|
||||
extern int main(int argc, char **argv);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: android_main
|
||||
// Description: This function is called by native_app_glue to
|
||||
// initialize the program. It simply stores the
|
||||
// android_app object and calls main() normally.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void android_main(struct android_app* app) {
|
||||
panda_android_app = app;
|
||||
|
||||
// Attach the current thread to the JVM.
|
||||
JNIEnv *env;
|
||||
ANativeActivity* activity = app->activity;
|
||||
int status = activity->vm->AttachCurrentThread(&env, NULL);
|
||||
if (status < 0 || env == NULL) {
|
||||
android_cat.error() << "Failed to attach thread to JVM!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the path to the APK.
|
||||
jclass clazz = env->GetObjectClass(activity->clazz);
|
||||
jmethodID methodID = env->GetMethodID(clazz, "getPackageCodePath", "()Ljava/lang/String;");
|
||||
jstring code_path = (jstring) env->CallObjectMethod(activity->clazz, methodID);
|
||||
|
||||
const char* apk_path;
|
||||
apk_path = env->GetStringUTFChars(code_path, NULL);
|
||||
android_cat.info() << "Path to APK: " << apk_path << "\n";
|
||||
|
||||
// Mount the assets directory.
|
||||
PT(VirtualFileMountAndroidAsset) asset_mount;
|
||||
asset_mount = new VirtualFileMountAndroidAsset(app->activity->assetManager, apk_path);
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
vfs->mount(asset_mount, "/android_asset", 0);
|
||||
|
||||
// Release the apk_path.
|
||||
env->ReleaseStringUTFChars(code_path, apk_path);
|
||||
|
||||
// Now add the asset directory to the model-path.
|
||||
get_model_path().append_directory("/android_asset");
|
||||
|
||||
// Create bogus argc and argv, then call our main function.
|
||||
char *argv[] = {NULL};
|
||||
int argc = 0;
|
||||
main(argc, argv);
|
||||
|
||||
// Detach the thread before exiting.
|
||||
activity->vm->DetachCurrentThread();
|
||||
}
|
88
panda/src/android/config_android.cxx
Normal file
88
panda/src/android/config_android.cxx
Normal file
@ -0,0 +1,88 @@
|
||||
// Filename: config_android.cxx
|
||||
// Created by: rdb (12Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_android.h"
|
||||
#include "pnmFileTypeAndroid.h"
|
||||
#include "pnmFileTypeRegistry.h"
|
||||
#include "dconfig.h"
|
||||
#include "pandaSystem.h"
|
||||
|
||||
NotifyCategoryDef(android, "");
|
||||
|
||||
struct android_app *panda_android_app = NULL;
|
||||
|
||||
jclass jni_PandaActivity;
|
||||
jmethodID jni_PandaActivity_readBitmapSize;
|
||||
jmethodID jni_PandaActivity_readBitmap;
|
||||
|
||||
jclass jni_BitmapFactory_Options;
|
||||
jfieldID jni_BitmapFactory_Options_outWidth;
|
||||
jfieldID jni_BitmapFactory_Options_outHeight;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: init_libandroid
|
||||
// Description: Initializes the library. This must be called at
|
||||
// least once before any of the functions or classes
|
||||
// in this library can be used. Normally, this is
|
||||
// called by JNI_OnLoad.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
init_libandroid() {
|
||||
PNMFileTypeRegistry *tr = PNMFileTypeRegistry::get_global_ptr();
|
||||
PNMFileTypeAndroid::init_type();
|
||||
PNMFileTypeAndroid::register_with_read_factory();
|
||||
tr->register_type(new PNMFileTypeAndroid);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: JNI_OnLoad
|
||||
// Description: Called by Java when loading this library.
|
||||
// Initializes the global class references and the
|
||||
// method IDs.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
jint JNI_OnLoad(JavaVM *jvm, void *reserved) {
|
||||
init_libandroid();
|
||||
|
||||
JNIEnv *env = get_jni_env();
|
||||
assert(env != NULL);
|
||||
|
||||
jni_PandaActivity = env->FindClass("org/panda3d/android/PandaActivity");
|
||||
jni_PandaActivity = (jclass) env->NewGlobalRef(jni_PandaActivity);
|
||||
|
||||
jni_PandaActivity_readBitmapSize = env->GetStaticMethodID(jni_PandaActivity,
|
||||
"readBitmapSize", "(J)Landroid/graphics/BitmapFactory$Options;");
|
||||
|
||||
jni_PandaActivity_readBitmap = env->GetStaticMethodID(jni_PandaActivity,
|
||||
"readBitmap", "(JI)Landroid/graphics/Bitmap;");
|
||||
|
||||
jni_BitmapFactory_Options = env->FindClass("android/graphics/BitmapFactory$Options");
|
||||
jni_BitmapFactory_Options = (jclass) env->NewGlobalRef(jni_BitmapFactory_Options);
|
||||
|
||||
jni_BitmapFactory_Options_outWidth = env->GetFieldID(jni_BitmapFactory_Options, "outWidth", "I");
|
||||
jni_BitmapFactory_Options_outHeight = env->GetFieldID(jni_BitmapFactory_Options, "outHeight", "I");
|
||||
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: JNI_OnUnload
|
||||
// Description: Called by Java when unloading this library.
|
||||
// Destroys the global class references.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void JNI_OnUnload(JavaVM *jvm, void *reserved) {
|
||||
JNIEnv *env = get_jni_env();
|
||||
|
||||
env->DeleteGlobalRef(jni_PandaActivity);
|
||||
env->DeleteGlobalRef(jni_BitmapFactory_Options);
|
||||
}
|
39
panda/src/android/config_android.h
Normal file
39
panda/src/android/config_android.h
Normal file
@ -0,0 +1,39 @@
|
||||
// Filename: config_android.h
|
||||
// Created by: rdb (12Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONFIG_ANDROID_H
|
||||
#define CONFIG_ANDROID_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "notifyCategoryProxy.h"
|
||||
#include "configVariableString.h"
|
||||
#include "configVariableBool.h"
|
||||
#include "configVariableInt.h"
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
NotifyCategoryDeclNoExport(android);
|
||||
extern void init_libandroid();
|
||||
|
||||
extern struct android_app* panda_android_app;
|
||||
|
||||
extern jclass jni_PandaActivity;
|
||||
extern jmethodID jni_PandaActivity_readBitmapHeader;
|
||||
extern jmethodID jni_PandaActivity_readBitmap;
|
||||
|
||||
extern jclass jni_BitmapFactory_Options;
|
||||
extern jfieldID jni_BitmapFactory_Options_outWidth;
|
||||
extern jfieldID jni_BitmapFactory_Options_outHeight;
|
||||
|
||||
#endif
|
71
panda/src/android/jni_NativeIStream.cxx
Normal file
71
panda/src/android/jni_NativeIStream.cxx
Normal file
@ -0,0 +1,71 @@
|
||||
// Filename: jni_NativeIStream.cxx
|
||||
// Created by: rdb (22Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <istream>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NativeIStream::nativeGet
|
||||
// Access: Private, Static
|
||||
// Description: Reads a single character from the istream.
|
||||
// Should return -1 on EOF.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
extern "C" jint
|
||||
Java_org_panda3d_android_NativeIStream_nativeGet(JNIEnv *env, jclass clazz, jlong ptr) {
|
||||
std::istream *stream = (std::istream *) ptr;
|
||||
|
||||
int ch = stream->get();
|
||||
return stream->good() ? ch : -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NativeIStream::nativeRead
|
||||
// Access: Private, Static
|
||||
// Description: Reads an array of bytes from the istream. Returns
|
||||
// the actual number of bytes that were read.
|
||||
// Should return -1 on EOF.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
extern "C" jint
|
||||
Java_org_panda3d_android_NativeIStream_nativeRead(JNIEnv *env, jclass clazz, jlong ptr, jbyteArray byte_array, jint offset, jint length) {
|
||||
std::istream *stream = (std::istream *) ptr;
|
||||
jbyte *buffer = (jbyte *) env->GetPrimitiveArrayCritical(byte_array, NULL);
|
||||
if (buffer == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
stream->read((char*) buffer + offset, length);
|
||||
env->ReleasePrimitiveArrayCritical(byte_array, buffer, 0);
|
||||
|
||||
// We have to return -1 on EOF, otherwise it will keep trying to read.
|
||||
size_t count = stream->gcount();
|
||||
if (count == 0 && stream->eof()) {
|
||||
return -1;
|
||||
} else {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NativeIStream::nativeIgnore
|
||||
// Access: Private, Static
|
||||
// Description: Skips ahead N bytes in the stream. Returns the
|
||||
// actual number of skipped bytes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
extern "C" jlong
|
||||
Java_org_panda3d_android_NativeIStream_nativeIgnore(JNIEnv *env, jclass clazz, jlong ptr, jlong offset) {
|
||||
std::istream *stream = (std::istream *) ptr;
|
||||
stream->ignore(offset);
|
||||
return stream->gcount();
|
||||
}
|
4
panda/src/android/p3android_composite1.cxx
Executable file
4
panda/src/android/p3android_composite1.cxx
Executable file
@ -0,0 +1,4 @@
|
||||
#include "config_android.cxx"
|
||||
#include "jni_NativeIStream.cxx"
|
||||
#include "pnmFileTypeAndroid.cxx"
|
||||
#include "pnmFileTypeAndroidReader.cxx"
|
127
panda/src/android/pnmFileTypeAndroid.cxx
Normal file
127
panda/src/android/pnmFileTypeAndroid.cxx
Normal file
@ -0,0 +1,127 @@
|
||||
// Filename: pnmFileTypeAndroid.cxx
|
||||
// Created by: rdb (11Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pnmFileTypeAndroid.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#include "config_pnmimagetypes.h"
|
||||
|
||||
#include "pnmFileTypeRegistry.h"
|
||||
#include "bamReader.h"
|
||||
|
||||
static const char * const extensions_android[] = {
|
||||
"jpg", "jpeg", "gif", "png",//"webp" (android 4.0+)
|
||||
};
|
||||
static const int num_extensions_android = sizeof(extensions_android) / sizeof(const char *);
|
||||
|
||||
TypeHandle PNMFileTypeAndroid::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMFileTypeAndroid::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PNMFileTypeAndroid::
|
||||
PNMFileTypeAndroid() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMFileTypeAndroid::get_name
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns a few words describing the file type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PNMFileTypeAndroid::
|
||||
get_name() const {
|
||||
return "Android Bitmap";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMFileTypeAndroid::get_num_extensions
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the number of different possible filename
|
||||
// extensions associated with this particular file type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PNMFileTypeAndroid::
|
||||
get_num_extensions() const {
|
||||
return num_extensions_android;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMFileTypeAndroid::get_extension
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the nth possible filename extension
|
||||
// associated with this particular file type, without a
|
||||
// leading dot.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PNMFileTypeAndroid::
|
||||
get_extension(int n) const {
|
||||
nassertr(n >= 0 && n < num_extensions_android, string());
|
||||
return extensions_android[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMFileTypeAndroid::has_magic_number
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if this particular file type uses a
|
||||
// magic number to identify it, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PNMFileTypeAndroid::
|
||||
has_magic_number() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMFileTypeAndroid::make_reader
|
||||
// Access: Public, Virtual
|
||||
// Description: Allocates and returns a new PNMReader suitable for
|
||||
// reading from this file type, if possible. If reading
|
||||
// from this file type is not supported, returns NULL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PNMReader *PNMFileTypeAndroid::
|
||||
make_reader(istream *file, bool owns_file, const string &magic_number) {
|
||||
init_pnm();
|
||||
return new Reader(this, file, owns_file, magic_number);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMFileTypeAndroid::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Registers the current object as something that can be
|
||||
// read from a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PNMFileTypeAndroid::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->
|
||||
register_factory(get_class_type(), make_PNMFileTypeAndroid);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMFileTypeAndroid::make_PNMFileTypeAndroid
|
||||
// Access: Protected, Static
|
||||
// Description: This method is called by the BamReader when an object
|
||||
// of this type is encountered in a Bam file; it should
|
||||
// allocate and return a new object with all the data
|
||||
// read.
|
||||
//
|
||||
// In the case of the PNMFileType objects, since these
|
||||
// objects are all shared, we just pull the object from
|
||||
// the registry.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable *PNMFileTypeAndroid::
|
||||
make_PNMFileTypeAndroid(const FactoryParams ¶ms) {
|
||||
return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type());
|
||||
}
|
||||
|
||||
#endif // ANDROID
|
93
panda/src/android/pnmFileTypeAndroid.h
Normal file
93
panda/src/android/pnmFileTypeAndroid.h
Normal file
@ -0,0 +1,93 @@
|
||||
// Filename: pnmFileTypeAndroid.h
|
||||
// Created by: rdb (11Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PNMFILETYPEANDROID_H
|
||||
#define PNMFILETYPEANDROID_H
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "pnmFileType.h"
|
||||
#include "pnmReader.h"
|
||||
#include "pnmWriter.h"
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PNMFileTypeAndroid
|
||||
// Description : Wrapper class around the Android Bitmap mechanism
|
||||
// to allow loading images on Android without needing
|
||||
// libpng or libjpeg.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_PNMIMAGETYPES PNMFileTypeAndroid : public PNMFileType {
|
||||
public:
|
||||
PNMFileTypeAndroid();
|
||||
|
||||
virtual string get_name() const;
|
||||
|
||||
virtual int get_num_extensions() const;
|
||||
virtual string get_extension(int n) const;
|
||||
|
||||
virtual bool has_magic_number() const;
|
||||
|
||||
virtual PNMReader *make_reader(istream *file, bool owns_file = true,
|
||||
const string &magic_number = string());
|
||||
|
||||
public:
|
||||
class Reader : public PNMReader {
|
||||
public:
|
||||
Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number);
|
||||
virtual ~Reader();
|
||||
|
||||
virtual void prepare_read();
|
||||
virtual int read_data(xel *array, xelval *alpha);
|
||||
|
||||
private:
|
||||
// It is assumed that the Reader is only used within a single thread.
|
||||
JNIEnv *_env;
|
||||
jobject _bitmap;
|
||||
int _sample_size;
|
||||
uint32_t _stride;
|
||||
int32_t _format;
|
||||
};
|
||||
|
||||
// The TypedWritable interface follows.
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_PNMFileTypeAndroid(const FactoryParams ¶ms);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
PNMFileType::init_type();
|
||||
register_type(_type_handle, "PNMFileTypeAndroid",
|
||||
PNMFileType::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#endif // ANDROID
|
||||
|
||||
#endif
|
303
panda/src/android/pnmFileTypeAndroidReader.cxx
Normal file
303
panda/src/android/pnmFileTypeAndroidReader.cxx
Normal file
@ -0,0 +1,303 @@
|
||||
// Filename: pnmFileTypeAndroidReader.cxx
|
||||
// Created by: rdb (22Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pnmFileTypeAndroid.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#include "config_pnmimagetypes.h"
|
||||
#include "config_express.h"
|
||||
|
||||
#include <android/bitmap.h>
|
||||
#include <jni.h>
|
||||
|
||||
// These tables linearly map 4-bit, 5-bit or 6-bit to 8-bit values.
|
||||
static uint8_t scale_table_4[16];
|
||||
static uint8_t scale_table_5[32];
|
||||
static uint8_t scale_table_6[64];
|
||||
|
||||
static void init_scale_tables() {
|
||||
static bool initialized = false;
|
||||
if (!initialized) {
|
||||
int i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
scale_table_4[i] = 255 * i / 15;
|
||||
}
|
||||
for (i = 0; i < 32; ++i) {
|
||||
scale_table_5[i] = 255 * i / 31;
|
||||
}
|
||||
for (i = 0; i < 64; ++i) {
|
||||
scale_table_6[i] = 255 * i / 63;
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void conv_rgb565(uint16_t in, xel &out) {
|
||||
out.r = scale_table_5[(in >> 11) & 31];
|
||||
out.g = scale_table_6[(in >> 5) & 63];
|
||||
out.b = scale_table_5[in & 31];
|
||||
}
|
||||
|
||||
static void conv_rgba4444(uint16_t in, xel &rgb, xelval &alpha) {
|
||||
rgb.r = scale_table_4[(in >> 12) & 0xF];
|
||||
rgb.g = scale_table_4[(in >> 8) & 0xF];
|
||||
rgb.b = scale_table_4[(in >> 4) & 0xF];
|
||||
alpha = scale_table_4[in & 0xF];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMFileTypeAndroid::Reader::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PNMFileTypeAndroid::Reader::
|
||||
Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
|
||||
PNMReader(type, file, owns_file), _bitmap(NULL)
|
||||
{
|
||||
// Hope we can putback() more than one character.
|
||||
for (string::reverse_iterator mi = magic_number.rbegin();
|
||||
mi != magic_number.rend(); ++mi) {
|
||||
_file->putback(*mi);
|
||||
};
|
||||
if (_file->fail()) {
|
||||
android_cat.error()
|
||||
<< "Unable to put back magic number.\n";
|
||||
_is_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
streampos pos = _file->tellg();
|
||||
_env = get_jni_env();
|
||||
jobject opts = _env->CallStaticObjectMethod(jni_PandaActivity,
|
||||
jni_PandaActivity_readBitmapSize,
|
||||
(jlong) _file);
|
||||
_file->seekg(pos);
|
||||
if (_file->tellg() != pos) {
|
||||
android_cat.error()
|
||||
<< "Unable to seek back to beginning.\n";
|
||||
_is_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_x_size = _env->GetIntField(opts, jni_BitmapFactory_Options_outWidth);
|
||||
_y_size = _env->GetIntField(opts, jni_BitmapFactory_Options_outHeight);
|
||||
|
||||
if (_x_size < 0 || _y_size < 0) {
|
||||
android_cat.error()
|
||||
<< "Failed to read header of " << *this << "\n";
|
||||
_is_valid = false;
|
||||
}
|
||||
|
||||
// Apparently we have to know this even though we don't yet.
|
||||
_num_channels = 4;
|
||||
_maxval = 255;
|
||||
|
||||
if (android_cat.is_debug()) {
|
||||
android_cat.debug()
|
||||
<< "Reading " << *this << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMFileTypeAndroid::Reader::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PNMFileTypeAndroid::Reader::
|
||||
~Reader() {
|
||||
if (_bitmap != NULL) {
|
||||
_env->DeleteGlobalRef(_bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMFileTypeAndroid::Reader::prepare_read
|
||||
// Access: Public, Virtual
|
||||
// Description: This method will be called before read_data() or
|
||||
// read_row() is called. It instructs the reader to
|
||||
// initialize its data structures as necessary to
|
||||
// actually perform the read operation.
|
||||
//
|
||||
// After this call, _x_size and _y_size should reflect
|
||||
// the actual size that will be filled by read_data()
|
||||
// (as possibly modified by set_read_size()).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PNMFileTypeAndroid::Reader::
|
||||
prepare_read() {
|
||||
_sample_size = 2;
|
||||
_orig_x_size = _x_size;
|
||||
_orig_y_size = _y_size;
|
||||
|
||||
if (_has_read_size && _read_x_size != 0 && _read_y_size != 0) {
|
||||
int x_reduction = _orig_x_size / _read_x_size;
|
||||
int y_reduction = _orig_y_size / _read_y_size;
|
||||
|
||||
_sample_size = max(min(x_reduction, y_reduction), 1);
|
||||
}
|
||||
|
||||
_bitmap = _env->CallStaticObjectMethod(jni_PandaActivity,
|
||||
jni_PandaActivity_readBitmap,
|
||||
(jlong) _file, _sample_size);
|
||||
|
||||
if (_bitmap == NULL) {
|
||||
android_cat.error()
|
||||
<< "Failed to read " << *this << "\n";
|
||||
_is_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_bitmap = _env->NewGlobalRef(_bitmap);
|
||||
|
||||
AndroidBitmapInfo info;
|
||||
if (AndroidBitmap_getInfo(_env, _bitmap, &info) < 0) {
|
||||
android_cat.error()
|
||||
<< "Failed to get info of " << *this << "\n";
|
||||
_is_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_x_size = info.width;
|
||||
_y_size = info.height;
|
||||
_format = info.format;
|
||||
_stride = info.stride;
|
||||
|
||||
// Note: we could be setting maxval more appropriately,
|
||||
// but this only causes texture.cxx to end up rescaling it later.
|
||||
// Best to do the scaling ourselves, using efficient tables.
|
||||
_maxval = 255;
|
||||
|
||||
switch (info.format) {
|
||||
case ANDROID_BITMAP_FORMAT_RGBA_8888:
|
||||
_num_channels = 4;
|
||||
android_cat.debug()
|
||||
<< "Bitmap has format RGBA_8888\n";
|
||||
break;
|
||||
case ANDROID_BITMAP_FORMAT_RGB_565:
|
||||
_num_channels = 3;
|
||||
android_cat.debug()
|
||||
<< "Bitmap has format RGB_565\n";
|
||||
break;
|
||||
case ANDROID_BITMAP_FORMAT_RGBA_4444:
|
||||
_num_channels = 4;
|
||||
android_cat.debug()
|
||||
<< "Bitmap has format RGBA_4444\n";
|
||||
break;
|
||||
case ANDROID_BITMAP_FORMAT_A_8:
|
||||
_num_channels = 1;
|
||||
android_cat.debug()
|
||||
<< "Bitmap has format A_8\n";
|
||||
break;
|
||||
default:
|
||||
android_cat.error()
|
||||
<< "Unsupported bitmap format!\n";
|
||||
_num_channels = 0;
|
||||
_is_valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMFileTypeAndroid::Reader::read_data
|
||||
// Access: Public, Virtual
|
||||
// Description: Reads in an entire image all at once, storing it in
|
||||
// the pre-allocated _x_size * _y_size array and alpha
|
||||
// pointers. (If the image type has no alpha channel,
|
||||
// alpha is ignored.) Returns the number of rows
|
||||
// correctly read.
|
||||
//
|
||||
// Derived classes need not override this if they
|
||||
// instead provide supports_read_row() and read_row(),
|
||||
// below.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PNMFileTypeAndroid::Reader::
|
||||
read_data(xel *rgb, xelval *alpha) {
|
||||
if (!_is_valid) {
|
||||
return 0;
|
||||
}
|
||||
void *ptr;
|
||||
if (AndroidBitmap_lockPixels(_env, _bitmap, &ptr) < 0) {
|
||||
android_cat.error()
|
||||
<< "Failed to lock bitmap for reading.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (_format) {
|
||||
case ANDROID_BITMAP_FORMAT_RGBA_8888: {
|
||||
nassertr(_stride == _x_size * 4, 0);
|
||||
uint8_t *data = (uint8_t *) ptr;
|
||||
for (int y = 0; y < _y_size; ++y) {
|
||||
for (int x = 0; x < _x_size; ++x) {
|
||||
rgb[x].r = data[0];
|
||||
rgb[x].g = data[1];
|
||||
rgb[x].b = data[2];
|
||||
alpha[x] = data[3];
|
||||
data += 4;
|
||||
}
|
||||
rgb += _x_size;
|
||||
alpha += _y_size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ANDROID_BITMAP_FORMAT_RGB_565: {
|
||||
nassertr(_stride == _x_size * 2, 0);
|
||||
init_scale_tables();
|
||||
|
||||
uint16_t *data = (uint16_t *) ptr;
|
||||
for (int y = 0; y < _y_size; ++y) {
|
||||
for (int x = 0; x < _x_size; ++x) {
|
||||
conv_rgb565(data[x], rgb[x]);
|
||||
}
|
||||
data += _x_size;
|
||||
rgb += _x_size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ANDROID_BITMAP_FORMAT_RGBA_4444: {
|
||||
nassertr(_stride == _x_size * 2, 0);
|
||||
init_scale_tables();
|
||||
|
||||
uint16_t *data = (uint16_t *) ptr;
|
||||
for (int y = 0; y < _y_size; ++y) {
|
||||
for (int x = 0; x < _x_size; ++x) {
|
||||
conv_rgba4444(data[x], rgb[x], alpha[x]);
|
||||
}
|
||||
data += _x_size;
|
||||
rgb += _x_size;
|
||||
alpha += _x_size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ANDROID_BITMAP_FORMAT_A_8: {
|
||||
nassertr(_stride == _x_size, 0);
|
||||
uint8_t *data = (uint8_t *) ptr;
|
||||
for (int y = 0; y < _y_size; ++y) {
|
||||
for (int x = 0; x < _x_size; ++x) {
|
||||
alpha[x] = data[x];
|
||||
}
|
||||
data += _x_size;
|
||||
alpha += _x_size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AndroidBitmap_unlockPixels(_env, _bitmap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
AndroidBitmap_unlockPixels(_env, _bitmap);
|
||||
return _y_size;
|
||||
}
|
||||
|
||||
#endif // ANDROID
|
100
panda/src/android/pview.cxx
Normal file
100
panda/src/android/pview.cxx
Normal file
@ -0,0 +1,100 @@
|
||||
// Filename: pview.cxx
|
||||
// Created by: rdb (12Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pandaFramework.h"
|
||||
#include "pandaSystem.h"
|
||||
#include "pystub.h"
|
||||
#include "texturePool.h"
|
||||
#include "multitexReducer.h"
|
||||
#include "sceneGraphReducer.h"
|
||||
#include "partGroup.h"
|
||||
#include "cardMaker.h"
|
||||
#include "bamCache.h"
|
||||
#include "virtualFileSystem.h"
|
||||
|
||||
// By including checkPandaVersion.h, we guarantee that runtime
|
||||
// attempts to run pview will fail if it inadvertently links with the
|
||||
// wrong version of libdtool.so/.dll.
|
||||
|
||||
#include "checkPandaVersion.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// A call to pystub() to force libpystub.so to be linked in.
|
||||
pystub();
|
||||
|
||||
PandaFramework framework;
|
||||
framework.open_framework(argc, argv);
|
||||
framework.set_window_title("Panda Viewer");
|
||||
|
||||
int hierarchy_match_flags = PartGroup::HMF_ok_part_extra |
|
||||
PartGroup::HMF_ok_anim_extra;
|
||||
|
||||
WindowFramework *window = framework.open_window();
|
||||
if (window != (WindowFramework *)NULL) {
|
||||
// We've successfully opened a window.
|
||||
|
||||
NodePath loading_np;
|
||||
|
||||
if (true) {
|
||||
// Put up a "loading" message for the user's benefit.
|
||||
NodePath aspect_2d = window->get_aspect_2d();
|
||||
PT(TextNode) loading = new TextNode("loading");
|
||||
loading_np = aspect_2d.attach_new_node(loading);
|
||||
loading_np.set_scale(0.125f);
|
||||
loading->set_text_color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
loading->set_shadow_color(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
loading->set_shadow(0.04, 0.04);
|
||||
loading->set_align(TextNode::A_center);
|
||||
loading->set_text("Loading...");
|
||||
|
||||
// Allow a couple of frames to go by so the window will be fully
|
||||
// created and the text will be visible.
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
framework.do_frame(current_thread);
|
||||
framework.do_frame(current_thread);
|
||||
}
|
||||
|
||||
window->enable_keyboard();
|
||||
window->setup_trackball();
|
||||
framework.get_models().instance_to(window->get_render());
|
||||
//if (argc < 2) {
|
||||
// If we have no arguments, get that trusty old triangle out.
|
||||
//window->load_default_model(framework.get_models());
|
||||
//} else {
|
||||
// window->load_models(framework.get_models(), argc, argv);
|
||||
//}
|
||||
|
||||
window->load_model(framework.get_models(), "panda-model.egg");
|
||||
window->load_model(framework.get_models(), "panda-walk4.egg");
|
||||
|
||||
window->loop_animations(hierarchy_match_flags);
|
||||
|
||||
// Make sure the textures are preloaded.
|
||||
framework.get_models().prepare_scene(window->get_graphics_output()->get_gsg());
|
||||
|
||||
loading_np.remove_node();
|
||||
|
||||
window->center_trackball(framework.get_models());
|
||||
window->set_anim_controls(true);
|
||||
|
||||
framework.enable_default_keys();
|
||||
framework.main_loop();
|
||||
framework.report_frame_rate(nout);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
framework.close_framework();
|
||||
return (0);
|
||||
}
|
24
panda/src/android/pview_manifest.xml
Executable file
24
panda/src/android/pview_manifest.xml
Executable file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- BEGIN_INCLUDE(manifest) -->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.panda3d.sdk"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-sdk android:minSdkVersion="9" />
|
||||
<application android:label="Panda Viewer" android:hasCode="true">
|
||||
<activity android:name="org.panda3d.android.PandaActivity"
|
||||
android:label="Panda Viewer" android:theme="@android:style/Theme.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden">
|
||||
|
||||
<meta-data android:name="android.app.lib_name"
|
||||
android:value="pview" />
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
<!-- END_INCLUDE(manifest) -->
|
@ -566,8 +566,8 @@ handle_motion_event(const AInputEvent *event) {
|
||||
_input_devices[0].button_up(MouseButton::one());
|
||||
}
|
||||
|
||||
float x = AMotionEvent_getX(event, 0);
|
||||
float y = AMotionEvent_getY(event, 0);
|
||||
float x = AMotionEvent_getX(event, 0) - _app->contentRect.left;
|
||||
float y = AMotionEvent_getY(event, 0) - _app->contentRect.top;
|
||||
|
||||
_input_devices[0].set_pointer_in_window(x, y);
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "virtualFile.h"
|
||||
#include "virtualFileComposite.h"
|
||||
#include "virtualFileMount.h"
|
||||
#include "virtualFileMountAndroidAsset.h"
|
||||
#include "virtualFileMountMultifile.h"
|
||||
#include "virtualFileMountRamdisk.h"
|
||||
#include "virtualFileMountSystem.h"
|
||||
@ -106,6 +107,9 @@ init_libexpress() {
|
||||
VirtualFile::init_type();
|
||||
VirtualFileComposite::init_type();
|
||||
VirtualFileMount::init_type();
|
||||
#ifdef ANDROID
|
||||
VirtualFileMountAndroidAsset::init_type();
|
||||
#endif
|
||||
VirtualFileMountMultifile::init_type();
|
||||
VirtualFileMountRamdisk::init_type();
|
||||
VirtualFileMountSystem::init_type();
|
||||
@ -191,3 +195,44 @@ get_config_express() {
|
||||
static DConfig config_express;
|
||||
return config_express;
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
static JavaVM *panda_jvm = NULL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: JNI_OnLoad
|
||||
// Description: Called by Java when loading this library.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
jint JNI_OnLoad(JavaVM *jvm, void *reserved) {
|
||||
panda_jvm = jvm;
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: get_java_vm
|
||||
// Description: Returns a pointer to the JavaVM object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
JavaVM *get_java_vm() {
|
||||
nassertr(panda_jvm != NULL, NULL);
|
||||
return panda_jvm;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: get_jni_env
|
||||
// Description: Returns a JNIEnv object for the current thread.
|
||||
// If it doesn't already exist, attaches the JVM
|
||||
// to this thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
JNIEnv *get_jni_env() {
|
||||
nassertr(panda_jvm != NULL, NULL);
|
||||
JNIEnv *env = NULL;
|
||||
int status = panda_jvm->GetEnv((void**) &env, JNI_VERSION_1_4);
|
||||
|
||||
if (status < 0 || env == NULL) {
|
||||
express_cat.error() << "JVM is not available in this thread!\n";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return env;
|
||||
}
|
||||
#endif
|
||||
|
@ -28,6 +28,10 @@
|
||||
// Include this so interrogate can find it.
|
||||
#include "executionEnvironment.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <jni.h>
|
||||
#endif
|
||||
|
||||
ConfigureDecl(config_express, EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS);
|
||||
NotifyCategoryDecl(express, EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS);
|
||||
NotifyCategoryDecl(clock, EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS);
|
||||
@ -62,4 +66,9 @@ END_PUBLISH
|
||||
|
||||
extern EXPCL_PANDAEXPRESS void init_libexpress();
|
||||
|
||||
#ifdef ANDROID
|
||||
extern EXPCL_PANDAEXPRESS JavaVM *get_java_vm();
|
||||
extern EXPCL_PANDAEXPRESS JNIEnv *get_jni_env();
|
||||
#endif
|
||||
|
||||
#endif /* __CONFIG_UTIL_H__ */
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "virtualFileComposite.cxx"
|
||||
#include "virtualFileList.cxx"
|
||||
#include "virtualFileMount.cxx"
|
||||
#include "virtualFileMountAndroidAsset.cxx"
|
||||
#include "virtualFileMountMultifile.cxx"
|
||||
#include "virtualFileMountRamdisk.cxx"
|
||||
#include "virtualFileMountSystem.cxx"
|
||||
|
35
panda/src/express/virtualFileMountAndroidAsset.I
Normal file
35
panda/src/express/virtualFileMountAndroidAsset.I
Normal file
@ -0,0 +1,35 @@
|
||||
// Filename: virtualFileMountAndroidAsset.cxx
|
||||
// Created by: rdb (21Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VirtualFileMountAndroidAsset::
|
||||
VirtualFileMountAndroidAsset(AAssetManager *mgr, const string &apk_path) :
|
||||
_asset_mgr(mgr), _apk_path(apk_path)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::AssetStream::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE VirtualFileMountAndroidAsset::AssetStream::
|
||||
AssetStream(AAsset *asset) :
|
||||
istream(new AssetStreamBuf(asset)) {
|
||||
}
|
420
panda/src/express/virtualFileMountAndroidAsset.cxx
Normal file
420
panda/src/express/virtualFileMountAndroidAsset.cxx
Normal file
@ -0,0 +1,420 @@
|
||||
// Filename: virtualFileMountAndroidAsset.cxx
|
||||
// Created by: rdb (21Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#include "virtualFileMountAndroidAsset.h"
|
||||
#include "virtualFileSystem.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
TypeHandle VirtualFileMountAndroidAsset::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VirtualFileMountAndroidAsset::
|
||||
~VirtualFileMountAndroidAsset() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::get_fd
|
||||
// Access: Public
|
||||
// Description: Returns a file descriptor that can be used to read
|
||||
// the asset if it was stored uncompressed and
|
||||
// unencrypted. Returns a valid fd or -1.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int VirtualFileMountAndroidAsset::
|
||||
get_fd(const Filename &file, off_t *start, off_t *length) const {
|
||||
AAsset* asset;
|
||||
asset = AAssetManager_open(_asset_mgr, file.c_str(), AASSET_MODE_UNKNOWN);
|
||||
|
||||
int fd = AAsset_openFileDescriptor(asset, start, length);
|
||||
AAsset_close(asset);
|
||||
return fd;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::has_file
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if the indicated file exists within the
|
||||
// mount system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool VirtualFileMountAndroidAsset::
|
||||
has_file(const Filename &file) const {
|
||||
return (file.empty() || is_directory(file) || is_regular_file(file));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::is_directory
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if the indicated file exists within the
|
||||
// mount system and is a directory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool VirtualFileMountAndroidAsset::
|
||||
is_directory(const Filename &file) const {
|
||||
// This is the only way - AAssetManager_openDir also works for files.
|
||||
//AAssetDir *dir = AAssetManager_openDir(_asset_mgr, file.c_str());
|
||||
|
||||
//express_cat.error() << "is_directory " << file << " - " << dir << "\n";
|
||||
|
||||
//if (dir == NULL) {
|
||||
// return false;
|
||||
//}
|
||||
//AAssetDir_close(dir);
|
||||
|
||||
// openDir doesn't return NULL for ordinary files!
|
||||
return !is_regular_file(file);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::is_regular_file
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if the indicated file exists within the
|
||||
// mount system and is a regular file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool VirtualFileMountAndroidAsset::
|
||||
is_regular_file(const Filename &file) const {
|
||||
// I'm afraid the only way to see if it exists is to try and open it.
|
||||
AAsset* asset;
|
||||
asset = AAssetManager_open(_asset_mgr, file.c_str(), AASSET_MODE_UNKNOWN);
|
||||
|
||||
express_cat.error() << "is_regular_file " << file << " - " << asset << "\n";
|
||||
|
||||
if (asset == NULL) {
|
||||
return false;
|
||||
}
|
||||
AAsset_close(asset);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::read_file
|
||||
// Access: Public, Virtual
|
||||
// Description: Fills up the indicated pvector with the contents of
|
||||
// the file, if it is a regular file. Returns true on
|
||||
// success, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool VirtualFileMountAndroidAsset::
|
||||
read_file(const Filename &file, bool do_uncompress,
|
||||
pvector<unsigned char> &result) const {
|
||||
if (do_uncompress) {
|
||||
// If the file is to be decompressed, we'd better just use the
|
||||
// higher-level implementation, which includes support for
|
||||
// on-the-fly decompression.
|
||||
return VirtualFileMount::read_file(file, do_uncompress, result);
|
||||
}
|
||||
|
||||
// But if we're just reading a straight file, let's just read
|
||||
// it here to avoid all of the streambuf nonsense.
|
||||
result.clear();
|
||||
|
||||
AAsset* asset;
|
||||
asset = AAssetManager_open(_asset_mgr, file.c_str(), AASSET_MODE_STREAMING);
|
||||
if (asset == (AAsset *)NULL) {
|
||||
express_cat.info()
|
||||
<< "Unable to read " << file << "\n";
|
||||
}
|
||||
|
||||
// Reserve enough space to hold the entire file.
|
||||
off_t file_size = AAsset_getLength(asset);
|
||||
if (file_size == 0) {
|
||||
return true;
|
||||
} else if (file_size > 0) {
|
||||
result.reserve((size_t)file_size);
|
||||
}
|
||||
|
||||
static const size_t buffer_size = 4096;
|
||||
char buffer[buffer_size];
|
||||
|
||||
int count = AAsset_read(asset, buffer, buffer_size);
|
||||
while (count > 0) {
|
||||
thread_consider_yield();
|
||||
result.insert(result.end(), buffer, buffer + count);
|
||||
count = AAsset_read(asset, buffer, buffer_size);
|
||||
}
|
||||
|
||||
AAsset_close(asset);
|
||||
return (count == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::open_read_file
|
||||
// Access: Public, Virtual
|
||||
// Description: Opens the file for reading, if it exists. Returns a
|
||||
// newly allocated istream on success (which you should
|
||||
// eventually delete when you are done reading).
|
||||
// Returns NULL on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
istream *VirtualFileMountAndroidAsset::
|
||||
open_read_file(const Filename &file) const {
|
||||
AAsset* asset;
|
||||
asset = AAssetManager_open(_asset_mgr, file.c_str(), AASSET_MODE_UNKNOWN);
|
||||
if (asset == (AAsset *)NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AssetStream *stream = new AssetStream(asset);
|
||||
return (istream *) stream;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::get_file_size
|
||||
// Access: Published, Virtual
|
||||
// Description: Returns the current size on disk (or wherever it is)
|
||||
// of the already-open file. Pass in the stream that
|
||||
// was returned by open_read_file(); some
|
||||
// implementations may require this stream to determine
|
||||
// the size.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
off_t VirtualFileMountAndroidAsset::
|
||||
get_file_size(const Filename &file, istream *in) const {
|
||||
// If it's already open, get the AAsset pointer from the streambuf.
|
||||
const AssetStreamBuf *buf = (const AssetStreamBuf *) in->rdbuf();
|
||||
off_t length = AAsset_getLength(buf->_asset);
|
||||
return length;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::get_file_size
|
||||
// Access: Published, Virtual
|
||||
// Description: Returns the current size on disk (or wherever it is)
|
||||
// of the file before it has been opened.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
off_t VirtualFileMountAndroidAsset::
|
||||
get_file_size(const Filename &file) const {
|
||||
AAsset* asset = AAssetManager_open(_asset_mgr, file.c_str(), AASSET_MODE_UNKNOWN);
|
||||
off_t length = AAsset_getLength(asset);
|
||||
AAsset_close(asset);
|
||||
return length;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::get_timestamp
|
||||
// Access: Published, Virtual
|
||||
// Description: Returns a time_t value that represents the time the
|
||||
// file was last modified, to within whatever precision
|
||||
// the operating system records this information (on a
|
||||
// Windows95 system, for instance, this may only be
|
||||
// accurate to within 2 seconds).
|
||||
//
|
||||
// If the timestamp cannot be determined, either because
|
||||
// it is not supported by the operating system or
|
||||
// because there is some error (such as file not found),
|
||||
// returns 0.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
time_t VirtualFileMountAndroidAsset::
|
||||
get_timestamp(const Filename &file) const {
|
||||
// There's no obvious way to get a timestamp from an Android asset.
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::get_system_info
|
||||
// Access: Public, Virtual
|
||||
// Description: Populates the SubfileInfo structure with the data
|
||||
// representing where the file actually resides on disk,
|
||||
// if this is knowable. Returns true if the file might
|
||||
// reside on disk, and the info is populated, or false
|
||||
// if it might not (or it is not known where the file
|
||||
// resides), in which case the info is meaningless.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool VirtualFileMountAndroidAsset::
|
||||
get_system_info(const Filename &file, SubfileInfo &info) {
|
||||
off_t start, length;
|
||||
int fd = get_fd(file, &start, &length);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Double-check that this fd actually points to the apk.
|
||||
struct stat st1, st2;
|
||||
nassertr(fstat(fd, &st1) == 0, false);
|
||||
nassertr(stat(_apk_path.c_str(), &st2) == 0, false);
|
||||
nassertr(st1.st_dev == st2.st_dev, false);
|
||||
nassertr(st1.st_ino == st2.st_ino, false);
|
||||
#endif
|
||||
|
||||
// We don't actually need the file descriptor, so close it.
|
||||
close(fd);
|
||||
|
||||
info = SubfileInfo(_apk_path, start, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::scan_directory
|
||||
// Access: Public, Virtual
|
||||
// Description: Fills the given vector up with the list of filenames
|
||||
// that are local to this directory, if the filename is
|
||||
// a directory. Returns true if successful, or false if
|
||||
// the file is not a directory or cannot be read.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool VirtualFileMountAndroidAsset::
|
||||
scan_directory(vector_string &contents, const Filename &dir) const {
|
||||
AAssetDir *asset_dir = AAssetManager_openDir(_asset_mgr, dir.c_str());
|
||||
if (asset_dir == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Note: this returns the full path.
|
||||
const char *fullpath = AAssetDir_getNextFileName(asset_dir);
|
||||
|
||||
while (fullpath != NULL) {
|
||||
express_cat.error() << fullpath << "\n"; // DEBUG
|
||||
// Determine the basename and add it to the vector.
|
||||
Filename fname (fullpath);
|
||||
contents.push_back(fname.get_basename());
|
||||
fullpath = AAssetDir_getNextFileName(asset_dir);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::AssetStream::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VirtualFileMountAndroidAsset::AssetStream::
|
||||
~AssetStream() {
|
||||
delete rdbuf();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::AssetStreamBuf::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VirtualFileMountAndroidAsset::AssetStreamBuf::
|
||||
AssetStreamBuf(AAsset *asset) :
|
||||
_asset(asset) {
|
||||
|
||||
#ifdef PHAVE_IOSTREAM
|
||||
char *buf = new char[4096];
|
||||
char *ebuf = buf + 4096;
|
||||
setg(buf, ebuf, ebuf);
|
||||
|
||||
#else
|
||||
allocate();
|
||||
setg(base(), ebuf(), ebuf());
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::AssetStreamBuf::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
VirtualFileMountAndroidAsset::AssetStreamBuf::
|
||||
~AssetStreamBuf() {
|
||||
AAsset_close(_asset);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::AssetStreamBuf::seekoff
|
||||
// Access: Public, Virtual
|
||||
// Description: Implements seeking within the stream.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
streampos VirtualFileMountAndroidAsset::AssetStreamBuf::
|
||||
seekoff(streamoff off, ios_seekdir dir, ios_openmode which) {
|
||||
size_t n = egptr() - gptr();
|
||||
|
||||
int whence;
|
||||
switch (dir) {
|
||||
case ios_base::beg:
|
||||
whence = SEEK_SET;
|
||||
break;
|
||||
case ios_base::cur:
|
||||
if (off == 0) {
|
||||
// Just requesting the current position,
|
||||
// no need to void the buffer.
|
||||
return AAsset_seek(_asset, 0, SEEK_CUR) - n;
|
||||
|
||||
} else if (gptr() + off >= eback() && gptr() + off < egptr()) {
|
||||
// We can seek around within the buffer.
|
||||
gbump(off);
|
||||
return AAsset_seek(_asset, 0, SEEK_CUR) - n + off;
|
||||
}
|
||||
whence = SEEK_CUR;
|
||||
break;
|
||||
case ios_base::end:
|
||||
whence = SEEK_END;
|
||||
break;
|
||||
default:
|
||||
return pos_type(-1);
|
||||
}
|
||||
gbump(n);
|
||||
return AAsset_seek(_asset, off, whence);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::AssetStreamBuf::seekpos
|
||||
// Access: Public, Virtual
|
||||
// Description: A variant on seekoff() to implement seeking within a
|
||||
// stream.
|
||||
//
|
||||
// The MSDN Library claims that it is only necessary to
|
||||
// redefine seekoff(), and not seekpos() as well, as the
|
||||
// default implementation of seekpos() is supposed to
|
||||
// map to seekoff() exactly as I am doing here; but in
|
||||
// fact it must do something else, because seeking
|
||||
// didn't work on Windows until I redefined this
|
||||
// function as well.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
streampos VirtualFileMountAndroidAsset::AssetStreamBuf::
|
||||
seekpos(streampos pos, ios_openmode which) {
|
||||
size_t n = egptr() - gptr();
|
||||
gbump(n);
|
||||
return AAsset_seek(_asset, pos, SEEK_SET);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VirtualFileMountAndroidAsset::AssetStreamBuf::underflow
|
||||
// Access: Protected, Virtual
|
||||
// Description: Called by the system istream implementation when its
|
||||
// internal buffer needs more characters.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int VirtualFileMountAndroidAsset::AssetStreamBuf::
|
||||
underflow() {
|
||||
// Sometimes underflow() is called even if the buffer is not empty.
|
||||
if (gptr() >= egptr()) {
|
||||
// Mark the buffer filled (with buffer_size bytes).
|
||||
size_t buffer_size = egptr() - eback();
|
||||
gbump(-(int)buffer_size);
|
||||
|
||||
streamsize read_count;
|
||||
read_count = AAsset_read(_asset, gptr(), buffer_size);
|
||||
|
||||
if (read_count != buffer_size) {
|
||||
// Oops, we didn't read what we thought we would.
|
||||
if (read_count == 0) {
|
||||
gbump(buffer_size);
|
||||
return EOF;
|
||||
}
|
||||
|
||||
// Slide what we did read to the top of the buffer.
|
||||
nassertr(read_count < buffer_size, EOF);
|
||||
size_t delta = buffer_size - read_count;
|
||||
memmove(gptr() + delta, gptr(), read_count);
|
||||
gbump(delta);
|
||||
}
|
||||
}
|
||||
|
||||
return (unsigned char)*gptr();
|
||||
}
|
||||
|
||||
#endif // ANDROID
|
107
panda/src/express/virtualFileMountAndroidAsset.h
Normal file
107
panda/src/express/virtualFileMountAndroidAsset.h
Normal file
@ -0,0 +1,107 @@
|
||||
// Filename: virtualFileMountAndroidAsset.h
|
||||
// Created by: rdb (21Jan13)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef VIRTUALFILEMOUNTANDROIDASSET_H
|
||||
#define VIRTUALFILEMOUNTANDROIDASSET_H
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "virtualFileMount.h"
|
||||
#include "multifile.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
#include <android/asset_manager.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : VirtualFileMountAndroidAsset
|
||||
// Description : Maps a Multifile's contents into the
|
||||
// VirtualFileSystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS VirtualFileMountAndroidAsset : public VirtualFileMount {
|
||||
PUBLISHED:
|
||||
INLINE VirtualFileMountAndroidAsset(AAssetManager *mgr, const string &apk_path);
|
||||
virtual ~VirtualFileMountAndroidAsset();
|
||||
|
||||
public:
|
||||
int get_fd(const Filename &file, off_t *start, off_t *end) const;
|
||||
|
||||
virtual bool has_file(const Filename &file) const;
|
||||
virtual bool is_directory(const Filename &file) const;
|
||||
virtual bool is_regular_file(const Filename &file) const;
|
||||
|
||||
virtual bool read_file(const Filename &file, bool do_uncompress,
|
||||
pvector<unsigned char> &result) const;
|
||||
|
||||
virtual istream *open_read_file(const Filename &file) const;
|
||||
virtual off_t get_file_size(const Filename &file, istream *stream) const;
|
||||
virtual off_t get_file_size(const Filename &file) const;
|
||||
virtual time_t get_timestamp(const Filename &file) const;
|
||||
virtual bool get_system_info(const Filename &file, SubfileInfo &info);
|
||||
|
||||
virtual bool scan_directory(vector_string &contents,
|
||||
const Filename &dir) const;
|
||||
|
||||
private:
|
||||
AAssetManager *_asset_mgr;
|
||||
string _apk_path;
|
||||
|
||||
class AssetStream : public istream {
|
||||
public:
|
||||
INLINE AssetStream(AAsset *asset);
|
||||
virtual ~AssetStream();
|
||||
};
|
||||
|
||||
class AssetStreamBuf : public streambuf {
|
||||
public:
|
||||
AssetStreamBuf(AAsset *asset);
|
||||
virtual ~AssetStreamBuf();
|
||||
|
||||
virtual streampos seekoff(streamoff off, ios_seekdir dir, ios_openmode which);
|
||||
virtual streampos seekpos(streampos pos, ios_openmode which);
|
||||
|
||||
protected:
|
||||
virtual int underflow();
|
||||
|
||||
private:
|
||||
AAsset *_asset;
|
||||
off_t _offset;
|
||||
|
||||
friend class VirtualFileMountAndroidAsset;
|
||||
};
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
VirtualFileMount::init_type();
|
||||
register_type(_type_handle, "VirtualFileMountAndroidAsset",
|
||||
VirtualFileMount::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "virtualFileMountAndroidAsset.I"
|
||||
|
||||
#endif // ANDROID
|
||||
|
||||
#endif
|
@ -127,7 +127,11 @@ VertexDataSaveFile(const Filename &directory, const string &prefix,
|
||||
|
||||
// Now try to lock the file, so we can be sure that no other
|
||||
// process is simultaneously writing to the same save file.
|
||||
#ifdef HAVE_LOCKF
|
||||
int result = lockf(_fd, F_TLOCK, 0);
|
||||
#else
|
||||
int result = flock(_fd, LOCK_EX | LOCK_NB);
|
||||
#endif
|
||||
if (result == 0) {
|
||||
// We've got the file. Truncate it first, for good measure, in
|
||||
// case there's an old version of the file we picked up.
|
||||
|
@ -22,6 +22,11 @@
|
||||
#include "config_pipeline.h"
|
||||
#include <sched.h>
|
||||
|
||||
#ifdef ANDROID
|
||||
#include "config_express.h"
|
||||
#include <jni.h>
|
||||
#endif
|
||||
|
||||
pthread_key_t ThreadPosixImpl::_pt_ptr_index = 0;
|
||||
bool ThreadPosixImpl::_got_pt_ptr_index = false;
|
||||
|
||||
@ -217,6 +222,18 @@ root_func(void *data) {
|
||||
self->_status = S_running;
|
||||
self->_mutex.release();
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
// Attach the Java VM to allow calling Java functions in this thread.
|
||||
JavaVM *jvm = get_java_vm();
|
||||
JNIEnv *env;
|
||||
if (jvm == NULL || jvm->AttachCurrentThread(&env, NULL) != 0) {
|
||||
thread_cat.error()
|
||||
<< "Failed to attach Java VM to thread "
|
||||
<< self->_parent_obj->get_name() << "!\n";
|
||||
env = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
self->_parent_obj->thread_main();
|
||||
|
||||
@ -235,7 +252,13 @@ root_func(void *data) {
|
||||
self->_status = S_finished;
|
||||
self->_mutex.release();
|
||||
}
|
||||
|
||||
|
||||
#ifdef ANDROID
|
||||
if (env != NULL) {
|
||||
jvm->DetachCurrentThread();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Now drop the parent object reference that we grabbed in start().
|
||||
// This might delete the parent object, and in turn, delete the
|
||||
// ThreadPosixImpl object.
|
||||
|
Loading…
x
Reference in New Issue
Block a user