0025195: Samples - add Java sample for Android 4.x
9
samples/java/jniviewer/.classpath
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||||
|
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||||
|
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="src" path="gen"/>
|
||||||
|
<classpathentry kind="output" path="bin/classes"/>
|
||||||
|
</classpath>
|
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
|
||||||
|
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <resources> <item path="/occtJniActivity/libs" type="2"/> </resources>}"/>
|
||||||
|
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
|
||||||
|
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="true"/>
|
||||||
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <resources> <item path="/occtJniActivity/jni" type="2"/> </resources>}"/>
|
||||||
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="~/develop/android-ndk-r10/ndk-build"/>
|
||||||
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
|
||||||
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="V=1 jniall"/>
|
||||||
|
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||||
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/occtJniActivity/jni}"/>
|
||||||
|
</launchConfiguration>
|
4
samples/java/jniviewer/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/assets
|
||||||
|
/bin
|
||||||
|
/gen
|
||||||
|
/libs
|
43
samples/java/jniviewer/.project
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>occtJniActivity</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||||
|
<triggers>auto,full,incremental,</triggers>
|
||||||
|
<arguments>
|
||||||
|
<dictionary>
|
||||||
|
<key>LaunchConfigHandle</key>
|
||||||
|
<value><project>/.externalToolBuilders/C++ Builder.launch</value>
|
||||||
|
</dictionary>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
@ -0,0 +1,4 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.6
|
36
samples/java/jniviewer/AndroidManifest.xml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.opencascade.jnisample">
|
||||||
|
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
|
||||||
|
<activity android:name="OcctJniActivity"
|
||||||
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:configChanges="orientation|keyboardHidden|screenSize">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data android:scheme="" />
|
||||||
|
<data android:scheme="file" />
|
||||||
|
<data android:scheme="content" />
|
||||||
|
<data android:host="*" />
|
||||||
|
|
||||||
|
<data android:pathPattern=".*\\.brep" />
|
||||||
|
<data android:pathPattern=".*\\.rle" />
|
||||||
|
<data android:pathPattern=".*\\.step" />
|
||||||
|
<data android:pathPattern=".*\\.stp" />
|
||||||
|
<data android:pathPattern=".*\\.iges" />
|
||||||
|
<data android:pathPattern=".*\\.igs" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
<uses-feature android:glEsVersion="0x00020000"/>
|
||||||
|
<uses-sdk android:minSdkVersion="15"/>
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
</manifest>
|
58
samples/java/jniviewer/ReadMe.md
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
OCCT JniViewer sample for Android {#samples_java_android_occt}
|
||||||
|
==================
|
||||||
|
|
||||||
|
This sample demonstrates simple way of using OCCT libraries in Android application written using Java.
|
||||||
|
|
||||||
|
The connection between Java and OCCT (C++) level is provided by proxy library, libTKJniSample.so, written in C++ with exported JNI methods of Java class OcctJniRenderer.
|
||||||
|
The proxy library contains single C++ class OcctJni_Viewer encapsulating OCCT viewer and providing functionality to manipulate this viewer
|
||||||
|
and to import OCCT shapes from several supported formats of CAD files (IGES, STEP, BREP).
|
||||||
|
|
||||||
|
This sample demonstrates indirect method of wrapping C++ to Java using manually created proxy library.
|
||||||
|
Alternative method is available, wrapping individual OCCT classes to Java equivalents so that their full API is available to Java user
|
||||||
|
and the code can be programmed on Java level similarly to C++ one.
|
||||||
|
See description of OCCT Java Wrapper in Advanced Samples and Tools on OCCT web site at
|
||||||
|
http://www.opencascade.org/support/products/advsamples
|
||||||
|
|
||||||
|
Run Eclipse from ADT (Android Developer Tools) for building the sample. To import sample project perform
|
||||||
|
~~~~
|
||||||
|
File -> Import... -> Android -> Existing Android code into Workspace
|
||||||
|
~~~~
|
||||||
|
and specify this directory. The project re-build will be started immediately right after importation if "Build automatically" option is turned on (default in Eclipse).
|
||||||
|
Proxy library compilation and packaging is performed by NDK build script, called by "C++ Builder" configured within Eclipse project.
|
||||||
|
The path to "ndk-build" tool from Android NDK (Native Development Kit) should be specified in Eclipse project properties:
|
||||||
|
~~~~
|
||||||
|
Project -> Properties -> Builders -> C++ Builder -> Edit -> Location
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
Now paths to OCCT C++ libraries and additional components should be specified in "jni/Android.mk" file:
|
||||||
|
~~~~
|
||||||
|
OCCT_ROOT := $(LOCAL_PATH)/../../../..
|
||||||
|
|
||||||
|
FREETYPE_INC := $(OCCT_ROOT)/../freetype/include/freetype2
|
||||||
|
FREETYPE_LIBS := $(OCCT_ROOT)/../freetype/libs
|
||||||
|
|
||||||
|
FREEIMAGE_INC := $(OCCT_ROOT)/../FreeImage/include
|
||||||
|
FREEIMAGE_LIBS := $(OCCT_ROOT)/../FreeImage/libs
|
||||||
|
|
||||||
|
OCCT_INC := $(OCCT_ROOT)/inc
|
||||||
|
OCCT_LIBS := $(OCCT_ROOT)/and/libs
|
||||||
|
~~~~
|
||||||
|
The list of extra components (Freetype, FreeImage) depends on OCCT configuration.
|
||||||
|
Variable $(TARGET_ARCH_ABI) is used within this script to refer to active architecture.
|
||||||
|
E.g. for 32-bit ARM build (see variable *APP_ABI* in "jni/Application.mk")
|
||||||
|
the folder *OCCT_LIBS* should contain sub-folder "armeabi-v7a" with OCCT libraries.
|
||||||
|
|
||||||
|
FreeImage is optional and does not required for this sample, however you should include all extra libraries used for OCCT building
|
||||||
|
and load the explicitly from Java code within OcctJniActivity::loadNatives() method, including toolkits from OCCT itself in proper order:
|
||||||
|
~~~~
|
||||||
|
if (!loadLibVerbose ("TKernel", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKMath", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKG2d", aLoaded, aFailed)
|
||||||
|
~~~~
|
||||||
|
Note that C++ STL library is not part of Android system.
|
||||||
|
Thus application must package this library as well as extra component.
|
||||||
|
"gnustl_shared" STL implementation is expected within this sample.
|
||||||
|
|
||||||
|
After successful build, the application can be packaged to Android:
|
||||||
|
- Deploy and run application on connected device or emulator directly from Eclipse using adb interface by menu items "Run" and "Debug". This would sign package with debug certificate.
|
||||||
|
- Prepare signed end-user package using wizard File -> Export -> Android -> Export Android Application.
|
215
samples/java/jniviewer/jni/Android.mk
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
LOCAL_PATH:= $(call my-dir)
|
||||||
|
|
||||||
|
STL_INC := $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/include $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/libs/$(TARGET_ARCH_ABI)/include
|
||||||
|
#STL_LIB := $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/libs/$(TARGET_ARCH_ABI)/libgnustl_static.a
|
||||||
|
STL_LIB := $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/libs/$(TARGET_ARCH_ABI)/libgnustl_shared.so
|
||||||
|
|
||||||
|
OCCT_ROOT := $(LOCAL_PATH)/../../../..
|
||||||
|
|
||||||
|
FREETYPE_INC := $(OCCT_ROOT)/../freetype/include/freetype2
|
||||||
|
FREETYPE_LIBS := $(OCCT_ROOT)/../freetype/libs
|
||||||
|
|
||||||
|
FREEIMAGE_INC := $(OCCT_ROOT)/../FreeImage/include
|
||||||
|
FREEIMAGE_LIBS := $(OCCT_ROOT)/../FreeImage/libs
|
||||||
|
|
||||||
|
OCCT_INC := $(OCCT_ROOT)/inc
|
||||||
|
OCCT_LIBS := $(OCCT_ROOT)/and/libs
|
||||||
|
|
||||||
|
ASSETDIR := $(LOCAL_PATH)/../assets
|
||||||
|
|
||||||
|
$(ASSETDIR)/Shaders: $(ASSETDIR)
|
||||||
|
-mkdir -p $(ASSETDIR)
|
||||||
|
-mkdir -p $(ASSETDIR)/Shaders
|
||||||
|
cp -f -r $(OCCT_ROOT)/src/Shaders/*.* $(ASSETDIR)/Shaders
|
||||||
|
|
||||||
|
$(ASSETDIR)/SHMessage: $(ASSETDIR)
|
||||||
|
-mkdir -p $(ASSETDIR)
|
||||||
|
-mkdir -p $(ASSETDIR)/SHMessage
|
||||||
|
cp -f -r $(OCCT_ROOT)/src/SHMessage/*.* $(ASSETDIR)/SHMessage
|
||||||
|
|
||||||
|
$(ASSETDIR)/XSMessage: $(ASSETDIR)
|
||||||
|
-mkdir -p $(ASSETDIR)
|
||||||
|
-mkdir -p $(ASSETDIR)/XSMessage
|
||||||
|
cp -f -r $(OCCT_ROOT)/src/XSMessage/*.* $(ASSETDIR)/XSMessage
|
||||||
|
|
||||||
|
$(ASSETDIR)/TObj: $(ASSETDIR)
|
||||||
|
-mkdir -p $(ASSETDIR)
|
||||||
|
-mkdir -p $(ASSETDIR)/TObj
|
||||||
|
cp -f -r $(OCCT_ROOT)/src/TObj/*.msg $(ASSETDIR)/TObj
|
||||||
|
|
||||||
|
$(ASSETDIR)/UnitsAPI: $(ASSETDIR)
|
||||||
|
-mkdir -p $(ASSETDIR)
|
||||||
|
-mkdir -p $(ASSETDIR)/UnitsAPI
|
||||||
|
cp -f -r $(OCCT_ROOT)/src/UnitsAPI/*.dat $(ASSETDIR)/UnitsAPI
|
||||||
|
|
||||||
|
pre_all: $(ASSETDIR)/Shaders $(ASSETDIR)/SHMessage $(ASSETDIR)/XSMessage $(ASSETDIR)/TObj $(ASSETDIR)/UnitsAPI
|
||||||
|
|
||||||
|
jniall: pre_all all
|
||||||
|
|
||||||
|
# STL libs
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := SharedStl
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(STL_INC)
|
||||||
|
LOCAL_SRC_FILES := $(STL_LIB)
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
# 3rd-parties used in OCCT
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := FreeType
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(FREETYPE_INC)
|
||||||
|
LOCAL_SRC_FILES := $(FREETYPE_LIBS)/$(TARGET_ARCH_ABI)/libfreetype.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
#include $(CLEAR_VARS)
|
||||||
|
#LOCAL_MODULE := FreeImage
|
||||||
|
#LOCAL_EXPORT_C_INCLUDES := $(FREEIMAGE_INC)
|
||||||
|
#LOCAL_SRC_FILES := $(FREEIMAGE_LIBS)/$(TARGET_ARCH_ABI)/libfreeimage.so
|
||||||
|
#include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
# OCCT core
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKernel
|
||||||
|
LOCAL_EXPORT_C_INCLUDES := $(OCCT_INC)
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKernel.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKMath
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKMath.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKG2d
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKG2d.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKG3d
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKG3d.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKGeomBase
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKGeomBase.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKBRep
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKBRep.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKGeomAlgo
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKGeomAlgo.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKTopAlgo
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKTopAlgo.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKShHealing
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKShHealing.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKMesh
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKMesh.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
# OCCT Exchange
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKPrim
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKPrim.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKBO
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKBO.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKBool
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKBool.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKFillet
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKFillet.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKOffset
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKOffset.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKXSBase
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKXSBase.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKIGES
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKIGES.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKSTEPBase
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKSTEPBase.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKSTEPAttr
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKSTEPAttr.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKSTEP209
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKSTEP209.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKSTEP
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKSTEP.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
# OCCT visualization
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKService
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKService.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKHLR
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKHLR.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKV3d
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKV3d.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := OcctTKOpenGl
|
||||||
|
LOCAL_SRC_FILES := $(OCCT_LIBS)/$(TARGET_ARCH_ABI)/libTKOpenGl.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
# our sample
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := libTKJniSample
|
||||||
|
LOCAL_C_INCLUDES := $(STL_INC)
|
||||||
|
#LOCAL_STATIC_LIBRARIES := $(STL_LIB) does not work
|
||||||
|
LOCAL_CFLAGS := -Wall
|
||||||
|
LOCAL_CPP_EXTENSION := .cxx .cpp
|
||||||
|
LOCAL_CPP_FEATURES := rtti exceptions
|
||||||
|
LOCAL_SRC_FILES := OcctJni_Viewer.cxx OcctJni_Window.cxx OcctJni_MsgPrinter.cxx
|
||||||
|
LOCAL_SHARED_LIBRARIES := OcctTKernel OcctTKMath OcctTKG2d OcctTKG3d OcctTKGeomBase OcctTKBRep OcctTKGeomAlgo OcctTKTopAlgo OcctTKShHealing OcctTKMesh OcctTKPrim
|
||||||
|
LOCAL_SHARED_LIBRARIES += OcctTKIGES OcctTKSTEP OcctTKXSBase
|
||||||
|
LOCAL_SHARED_LIBRARIES += OcctTKService OcctTKHLR OcctTKV3d OcctTKOpenGl
|
||||||
|
LOCAL_SHARED_LIBRARIES += SharedStl
|
||||||
|
LOCAL_LDLIBS := -llog -lGLESv2 -lEGL
|
||||||
|
|
||||||
|
#LOCAL_LDLIBS += $(STL_LIB)
|
||||||
|
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
8
samples/java/jniviewer/jni/Application.mk
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
NDK_TOOLCHAIN_VERSION := 4.8
|
||||||
|
APP_PLATFORM := android-15
|
||||||
|
|
||||||
|
APP_ABI := armeabi-v7a
|
||||||
|
#APP_ABI := all
|
||||||
|
|
||||||
|
#APP_STL := gnustl_static
|
||||||
|
#APP_STL := stlport_static
|
102
samples/java/jniviewer/jni/OcctJni_MsgPrinter.cxx
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// Copyright (c) 2014 OPEN CASCADE SAS
|
||||||
|
//
|
||||||
|
// This file is part of Open CASCADE Technology software library.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||||
|
// by the Free Software Foundation, with special exception defined in the file
|
||||||
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||||
|
// distribution for complete text of the license and disclaimer of any warranty.
|
||||||
|
//
|
||||||
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||||
|
// commercial license or contractual agreement.
|
||||||
|
|
||||||
|
#include <OcctJni_MsgPrinter.hxx>
|
||||||
|
|
||||||
|
#include <TCollection_AsciiString.hxx>
|
||||||
|
#include <TCollection_ExtendedString.hxx>
|
||||||
|
|
||||||
|
#include <android/log.h>
|
||||||
|
|
||||||
|
IMPLEMENT_STANDARD_HANDLE (OcctJni_MsgPrinter, Message_Printer)
|
||||||
|
IMPLEMENT_STANDARD_RTTIEXT(OcctJni_MsgPrinter, Message_Printer)
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : OcctJni_MsgPrinter
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
OcctJni_MsgPrinter::OcctJni_MsgPrinter (JNIEnv* theJEnv,
|
||||||
|
jobject theJObj)
|
||||||
|
: myJEnv (theJEnv),
|
||||||
|
myJObj (theJEnv->NewGlobalRef (theJObj)),
|
||||||
|
myJMet (NULL)
|
||||||
|
{
|
||||||
|
jclass aJClass = theJEnv->GetObjectClass (theJObj);
|
||||||
|
myJMet = theJEnv->GetMethodID (aJClass, "postMessage", "(Ljava/lang/String;)V");
|
||||||
|
if (myJMet == NULL)
|
||||||
|
{
|
||||||
|
__android_log_write (ANDROID_LOG_FATAL, "jniSample", "Broken initialization of OcctJni_MsgPrinter!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : ~OcctJni_MsgPrinter
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
OcctJni_MsgPrinter::~OcctJni_MsgPrinter()
|
||||||
|
{
|
||||||
|
//myJEnv->DeleteGlobalRef (myJObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : Send
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
void OcctJni_MsgPrinter::Send (const TCollection_ExtendedString& theString,
|
||||||
|
const Message_Gravity theGravity,
|
||||||
|
const Standard_Boolean theToPutEndl) const
|
||||||
|
{
|
||||||
|
if (theGravity >= myTraceLevel)
|
||||||
|
{
|
||||||
|
const TCollection_AsciiString aStr (theString);
|
||||||
|
OcctJni_MsgPrinter::Send (aStr, theGravity, theToPutEndl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : Send
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
void OcctJni_MsgPrinter::Send (const TCollection_AsciiString& theString,
|
||||||
|
const Message_Gravity theGravity,
|
||||||
|
const Standard_Boolean theToPutEndl) const
|
||||||
|
{
|
||||||
|
if (theGravity < myTraceLevel)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
///__android_log_write (ANDROID_LOG_DEBUG, "OcctJni_MsgPrinter", (TCollection_AsciiString(" @@ ") + theString).ToCString());
|
||||||
|
if (myJMet == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jstring aJStr = myJEnv->NewStringUTF ((theString + "\n").ToCString());
|
||||||
|
myJEnv->CallObjectMethod (myJObj, myJMet, aJStr);
|
||||||
|
myJEnv->DeleteLocalRef (aJStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : Send
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
void OcctJni_MsgPrinter::Send (const Standard_CString& theString,
|
||||||
|
const Message_Gravity theGravity,
|
||||||
|
const Standard_Boolean theToPutEndl) const
|
||||||
|
{
|
||||||
|
if (theGravity >= myTraceLevel)
|
||||||
|
{
|
||||||
|
OcctJni_MsgPrinter::Send (TCollection_AsciiString (theString), theGravity, theToPutEndl);
|
||||||
|
}
|
||||||
|
}
|
62
samples/java/jniviewer/jni/OcctJni_MsgPrinter.hxx
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Copyright (c) 2014 OPEN CASCADE SAS
|
||||||
|
//
|
||||||
|
// This file is part of Open CASCADE Technology software library.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||||
|
// by the Free Software Foundation, with special exception defined in the file
|
||||||
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||||
|
// distribution for complete text of the license and disclaimer of any warranty.
|
||||||
|
//
|
||||||
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||||
|
// commercial license or contractual agreement.
|
||||||
|
|
||||||
|
#ifndef OcctJni_MsgPrinter_H
|
||||||
|
#define OcctJni_MsgPrinter_H
|
||||||
|
|
||||||
|
#include <Message_Printer.hxx>
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
// Class providing connection between messenger interfaces in C++ and Java layers.
|
||||||
|
class OcctJni_MsgPrinter : public Message_Printer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Default constructor
|
||||||
|
OcctJni_MsgPrinter (JNIEnv* theJEnv,
|
||||||
|
jobject theJObj);
|
||||||
|
|
||||||
|
//! Destructor.
|
||||||
|
~OcctJni_MsgPrinter();
|
||||||
|
|
||||||
|
//! Redirection to TCollection_AsciiString method
|
||||||
|
virtual void Send (const TCollection_ExtendedString& theString,
|
||||||
|
const Message_Gravity theGravity,
|
||||||
|
const Standard_Boolean theToPutEndl) const;
|
||||||
|
|
||||||
|
//! Redirection to TCollection_AsciiString method
|
||||||
|
virtual void Send (const Standard_CString& theString,
|
||||||
|
const Message_Gravity theGravity,
|
||||||
|
const Standard_Boolean theToPutEndl) const;
|
||||||
|
|
||||||
|
//! Main printing method
|
||||||
|
virtual void Send (const TCollection_AsciiString& theString,
|
||||||
|
const Message_Gravity theGravity,
|
||||||
|
const Standard_Boolean theToPutEndl) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
JNIEnv* myJEnv;
|
||||||
|
jobject myJObj;
|
||||||
|
jmethodID myJMet;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DEFINE_STANDARD_RTTI(OcctJni_MsgPrinter)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_STANDARD_HANDLE(OcctJni_MsgPrinter, Message_Printer)
|
||||||
|
|
||||||
|
#endif // OcctJni_MsgPrinter_H
|
810
samples/java/jniviewer/jni/OcctJni_Viewer.cxx
Normal file
@ -0,0 +1,810 @@
|
|||||||
|
// Copyright (c) 2014 OPEN CASCADE SAS
|
||||||
|
//
|
||||||
|
// This file is part of Open CASCADE Technology software library.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||||
|
// by the Free Software Foundation, with special exception defined in the file
|
||||||
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||||
|
// distribution for complete text of the license and disclaimer of any warranty.
|
||||||
|
//
|
||||||
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||||
|
// commercial license or contractual agreement.
|
||||||
|
|
||||||
|
#include <OcctJni_Viewer.hxx>
|
||||||
|
#include <OcctJni_MsgPrinter.hxx>
|
||||||
|
|
||||||
|
#include <AIS_Shape.hxx>
|
||||||
|
#include <Image_AlienPixMap.hxx>
|
||||||
|
#include <BRepTools.hxx>
|
||||||
|
#include <Message_Messenger.hxx>
|
||||||
|
#include <Message_MsgFile.hxx>
|
||||||
|
#include <OpenGl_GraphicDriver.hxx>
|
||||||
|
#include <OSD_Environment.hxx>
|
||||||
|
#include <OSD_Timer.hxx>
|
||||||
|
#include <Standard_Version.hxx>
|
||||||
|
|
||||||
|
#include <BRepPrimAPI_MakeBox.hxx>
|
||||||
|
|
||||||
|
#include <STEPControl_Reader.hxx>
|
||||||
|
#include <IGESControl_Reader.hxx>
|
||||||
|
#include <XSControl_WorkSession.hxx>
|
||||||
|
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
//! @return true if file exists
|
||||||
|
static bool isFileExist (const TCollection_AsciiString& thePath)
|
||||||
|
{
|
||||||
|
struct stat64 aStatBuffer;
|
||||||
|
return stat64 (thePath.ToCString(), &aStatBuffer) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Cut-off the last split character from the path and everything after it.
|
||||||
|
static TCollection_AsciiString getParentDir (const TCollection_AsciiString& thePath)
|
||||||
|
{
|
||||||
|
TCollection_AsciiString aPath = thePath;
|
||||||
|
char* aSplitter = (char* )aPath.ToCString();
|
||||||
|
for (char* anIter = aSplitter; *anIter != '\0'; ++anIter)
|
||||||
|
{
|
||||||
|
if (*anIter == '\\'
|
||||||
|
|| *anIter == '/')
|
||||||
|
{
|
||||||
|
aSplitter = anIter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*aSplitter = '\0'; // cut off file name or trailing folder
|
||||||
|
return TCollection_AsciiString (aPath.ToCString());
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Set environment variable theVarName indicating location of resource
|
||||||
|
//! file theFile so as to correspond to actual location of this file.
|
||||||
|
//!
|
||||||
|
//! The resource file is searched in directory where Test.Draw.dll is located,
|
||||||
|
//! and if not found - also in subdirectory ../res from there.
|
||||||
|
//! If file is found, environment variable is set for C subsystem.
|
||||||
|
//! Otherwise, environment is not changed.
|
||||||
|
//!
|
||||||
|
//! If theToAddFileName is true, complete file name is set as value of the variable,
|
||||||
|
//! if theToAddFileName is false, only path is set.
|
||||||
|
Standard_Boolean setResourceEnv (const TCollection_AsciiString& theVarName,
|
||||||
|
const TCollection_AsciiString& theRoot,
|
||||||
|
const TCollection_AsciiString& theFile,
|
||||||
|
const Standard_Boolean theToAddFileName)
|
||||||
|
{
|
||||||
|
// use location of current assembly to figure out possible location of resource
|
||||||
|
TCollection_AsciiString aBaseDir = theRoot;
|
||||||
|
|
||||||
|
// check the same directory where binary is located
|
||||||
|
if (!isFileExist (aBaseDir + "/" + theFile))
|
||||||
|
{
|
||||||
|
// check subdirectory ../res
|
||||||
|
aBaseDir = getParentDir (aBaseDir) + "/res";
|
||||||
|
if (!isFileExist (aBaseDir + "/" + theFile))
|
||||||
|
{
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set C library environment
|
||||||
|
if (theToAddFileName)
|
||||||
|
{
|
||||||
|
aBaseDir = aBaseDir + "/" + theFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSD_Environment anEnv (theVarName, aBaseDir);
|
||||||
|
anEnv.Build();
|
||||||
|
return Standard_True;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : OcctJni_Viewer
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
OcctJni_Viewer::OcctJni_Viewer()
|
||||||
|
{
|
||||||
|
// prepare necessary environment
|
||||||
|
TCollection_AsciiString aResRoot = "/data/data/com.opencascade.jnisample/files";
|
||||||
|
|
||||||
|
setResourceEnv ("CSF_TObjMessage", aResRoot + "/TObj", "TObj.msg", Standard_False);
|
||||||
|
setResourceEnv ("CSF_UnitsLexicon", aResRoot + "/UnitsAPI", "Lexi_Expr.dat", Standard_True);
|
||||||
|
setResourceEnv ("CSF_UnitsDefinition", aResRoot + "/UnitsAPI", "Units.dat", Standard_True);
|
||||||
|
setResourceEnv ("CSF_ShadersDirectory", aResRoot + "/Shaders", "Declarations.glsl", Standard_False);
|
||||||
|
setResourceEnv ("CSF_XSMessage", aResRoot + "/XSMessage", "XSTEP.us", Standard_False);
|
||||||
|
setResourceEnv ("CSF_SHMessage", aResRoot + "/XSMessage", "SHAPE.us", Standard_False);
|
||||||
|
//setResourceEnv ("CSF_PluginDefaults", "Plugin", Standard_False);
|
||||||
|
|
||||||
|
// make sure OCCT loads the dictionary
|
||||||
|
//UnitsAPI::SetLocalSystem (UnitsAPI_SI);
|
||||||
|
|
||||||
|
// load messages for TObj
|
||||||
|
Message_MsgFile::LoadFromEnv ("CSF_TObjMessage", "TObj", "msg");
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : init
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
bool OcctJni_Viewer::init()
|
||||||
|
{
|
||||||
|
EGLint aCfgId = 0;
|
||||||
|
int aWidth = 0, aHeight = 0;
|
||||||
|
EGLDisplay anEglDisplay = eglGetCurrentDisplay();
|
||||||
|
EGLContext anEglContext = eglGetCurrentContext();
|
||||||
|
EGLSurface anEglSurf = eglGetCurrentSurface (EGL_DRAW);
|
||||||
|
if (anEglDisplay == EGL_NO_DISPLAY
|
||||||
|
|| anEglContext == EGL_NO_CONTEXT
|
||||||
|
|| anEglSurf == EGL_NO_SURFACE)
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Error: No active EGL context!", Message_Fail);
|
||||||
|
release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
eglQuerySurface (anEglDisplay, anEglSurf, EGL_WIDTH, &aWidth);
|
||||||
|
eglQuerySurface (anEglDisplay, anEglSurf, EGL_HEIGHT, &aHeight);
|
||||||
|
eglQuerySurface (anEglDisplay, anEglSurf, EGL_CONFIG_ID, &aCfgId);
|
||||||
|
const EGLint aConfigAttribs[] = { EGL_CONFIG_ID, aCfgId, EGL_NONE };
|
||||||
|
EGLint aNbConfigs = 0;
|
||||||
|
void* anEglConfig = NULL;
|
||||||
|
if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) != EGL_TRUE)
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Error: EGL does not provide compatible configurations!", Message_Fail);
|
||||||
|
release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TCollection_AsciiString anEglInfo = TCollection_AsciiString()
|
||||||
|
+ "\n EGLVersion: " + eglQueryString (anEglDisplay, EGL_VERSION)
|
||||||
|
+ "\n EGLVendor: " + eglQueryString (anEglDisplay, EGL_VENDOR)
|
||||||
|
+ "\n EGLClient APIs: " + eglQueryString (anEglDisplay, EGL_CLIENT_APIS)
|
||||||
|
+ "\n GLvendor: " + (const char* )glGetString (GL_VENDOR)
|
||||||
|
+ "\n GLdevice: " + (const char* )glGetString (GL_RENDERER)
|
||||||
|
+ "\n GLversion: " + (const char* )glGetString (GL_VERSION) + " [GLSL: " + (const char* )glGetString (GL_SHADING_LANGUAGE_VERSION) + "]";
|
||||||
|
::Message::DefaultMessenger()->Send (anEglInfo, Message_Info);
|
||||||
|
|
||||||
|
if (!myViewer.IsNull())
|
||||||
|
{
|
||||||
|
Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver());
|
||||||
|
Handle(OcctJni_Window) aWindow = Handle(OcctJni_Window)::DownCast (myView->Window());
|
||||||
|
if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Error: OpenGl_GraphicDriver can not be initialized!", Message_Fail);
|
||||||
|
release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aWindow->SetSize (aWidth, aHeight);
|
||||||
|
myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext, NULL, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (NULL, Standard_False);
|
||||||
|
aDriver->ChangeOptions().buffersNoSwap = Standard_True;
|
||||||
|
//aDriver->ChangeOptions().glslWarnings = Standard_True; /// for debug only!
|
||||||
|
if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Error: OpenGl_GraphicDriver can not be initialized!", Message_Fail);
|
||||||
|
release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create viewer
|
||||||
|
myViewer = new V3d_Viewer (aDriver, TCollection_ExtendedString("Viewer").ToExtString(), "", 1000.0,
|
||||||
|
V3d_XposYnegZpos, Quantity_NOC_BLACK, V3d_ZBUFFER, V3d_GOURAUD, V3d_WAIT,
|
||||||
|
Standard_True, Standard_False);
|
||||||
|
myViewer->SetDefaultLights();
|
||||||
|
myViewer->SetLightOn();
|
||||||
|
|
||||||
|
// create AIS context
|
||||||
|
myContext = new AIS_InteractiveContext (myViewer);
|
||||||
|
//myContext->SetDisplayMode (AIS_WireFrame);
|
||||||
|
myContext->SetDisplayMode (AIS_Shaded);
|
||||||
|
|
||||||
|
Handle(OcctJni_Window) aWindow = new OcctJni_Window (aWidth, aHeight);
|
||||||
|
myView = myViewer->CreateView();
|
||||||
|
|
||||||
|
myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext, NULL, NULL);
|
||||||
|
myView->TriedronDisplay (Aspect_TOTP_RIGHT_LOWER, Quantity_NOC_WHITE, 0.08, V3d_ZBUFFER);
|
||||||
|
|
||||||
|
initContent();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : release
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
void OcctJni_Viewer::release()
|
||||||
|
{
|
||||||
|
myContext.Nullify();
|
||||||
|
myView.Nullify();
|
||||||
|
myViewer.Nullify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : resize
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
void OcctJni_Viewer::resize (int theWidth,
|
||||||
|
int theHeight)
|
||||||
|
{
|
||||||
|
if (myContext.IsNull())
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Resize failed - view is unavailable", Message_Fail);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver());
|
||||||
|
Handle(OcctJni_Window) aWindow = Handle(OcctJni_Window)::DownCast (myView->Window());
|
||||||
|
aWindow->SetSize (theWidth, theHeight);
|
||||||
|
//myView->MustBeResized(); // can be used instead of SetWindow() when EGLsurface has not been changed
|
||||||
|
|
||||||
|
EGLContext anEglContext = eglGetCurrentContext();
|
||||||
|
myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext, NULL, NULL);
|
||||||
|
//saveSnapshot ("/sdcard/Download/tt.png", theWidth, theHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : initContent
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
void OcctJni_Viewer::initContent()
|
||||||
|
{
|
||||||
|
myContext->RemoveAll (Standard_False);
|
||||||
|
|
||||||
|
OSD_Timer aTimer;
|
||||||
|
aTimer.Start();
|
||||||
|
if (!myShape.IsNull())
|
||||||
|
{
|
||||||
|
Handle(AIS_Shape) aShapePrs = new AIS_Shape (myShape);
|
||||||
|
myContext->Display (aShapePrs, Standard_False);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BRepPrimAPI_MakeBox aBuilder (1.0, 2.0, 3.0);
|
||||||
|
Handle(AIS_Shape) aShapePrs = new AIS_Shape (aBuilder.Shape());
|
||||||
|
myContext->Display (aShapePrs, Standard_False);
|
||||||
|
}
|
||||||
|
myView->FitAll();
|
||||||
|
|
||||||
|
aTimer.Stop();
|
||||||
|
Message::DefaultMessenger()->Send (TCollection_AsciiString() + "Presentation computed in " + aTimer.ElapsedTime() + " seconds", Message_Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Load shape from IGES file
|
||||||
|
static TopoDS_Shape loadIGES (const TCollection_AsciiString& thePath)
|
||||||
|
{
|
||||||
|
TopoDS_Shape aShape;
|
||||||
|
IGESControl_Reader aReader;
|
||||||
|
IFSelect_ReturnStatus aReadStatus = IFSelect_RetFail;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
aReadStatus = aReader.ReadFile (thePath.ToCString());
|
||||||
|
}
|
||||||
|
catch (Standard_Failure)
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Error: IGES reader, computation error", Message_Fail);
|
||||||
|
return aShape;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aReadStatus != IFSelect_RetDone)
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Error: IGES reader, bad file format", Message_Fail);
|
||||||
|
return aShape;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now perform the translation
|
||||||
|
aReader.TransferRoots();
|
||||||
|
if (aReader.NbShapes() <= 0)
|
||||||
|
{
|
||||||
|
Handle(XSControl_WorkSession) aWorkSession = new XSControl_WorkSession();
|
||||||
|
aWorkSession->SelectNorm ("IGES");
|
||||||
|
aReader.SetWS (aWorkSession, Standard_True);
|
||||||
|
aReader.SetReadVisible (Standard_False);
|
||||||
|
aReader.TransferRoots();
|
||||||
|
}
|
||||||
|
if (aReader.NbShapes() <= 0)
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Error: IGES reader, no shapes has been found", Message_Fail);
|
||||||
|
return aShape;
|
||||||
|
}
|
||||||
|
return aReader.OneShape();
|
||||||
|
/*TopoDS_Shape anImportedShape = aReader.OneShape();
|
||||||
|
|
||||||
|
// apply sewing on the imported shape
|
||||||
|
BRepBuilderAPI_Sewing aTool (0.0);
|
||||||
|
aTool.SetNonManifoldMode (Standard_False);
|
||||||
|
aTool.SetFloatingEdgesMode(Standard_True);
|
||||||
|
aTool.Load (anImportedShape);
|
||||||
|
aTool.Perform();
|
||||||
|
TopoDS_Shape aSewedShape = aTool.SewedShape();
|
||||||
|
|
||||||
|
if (aSewedShape.IsNull())
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Error: Sewing result is empty", Message_Fail);
|
||||||
|
return aShape;
|
||||||
|
}
|
||||||
|
if (aSewedShape.IsSame(anImportedShape))
|
||||||
|
{
|
||||||
|
aShape = anImportedShape;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// apply shape healing
|
||||||
|
ShapeFix_Shape aShapeFixer(aSewedShape);
|
||||||
|
aShapeFixer.FixSolidMode() = 1;
|
||||||
|
aShapeFixer.FixFreeShellMode() = 1;
|
||||||
|
aShapeFixer.FixFreeFaceMode() = 1;
|
||||||
|
aShapeFixer.FixFreeWireMode() = 0;
|
||||||
|
aShapeFixer.FixSameParameterMode() = 0;
|
||||||
|
aShapeFixer.FixVertexPositionMode() = 0;
|
||||||
|
aShape = aShapeFixer.Perform() ? aShapeFixer.Shape() : aSewedShape;
|
||||||
|
}
|
||||||
|
return aShape;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Load shape from STEP file
|
||||||
|
static TopoDS_Shape loadSTEP (const TCollection_AsciiString& thePath)
|
||||||
|
{
|
||||||
|
STEPControl_Reader aReader;
|
||||||
|
IFSelect_ReturnStatus aReadStatus = IFSelect_RetFail;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
aReadStatus = aReader.ReadFile (thePath.ToCString());
|
||||||
|
}
|
||||||
|
catch (Standard_Failure)
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Error: STEP reader, computation error", Message_Fail);
|
||||||
|
return TopoDS_Shape();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aReadStatus != IFSelect_RetDone)
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Error: STEP reader, bad file format", Message_Fail);
|
||||||
|
return TopoDS_Shape();
|
||||||
|
}
|
||||||
|
else if (aReader.NbRootsForTransfer() <= 0)
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Error: STEP reader, shape is empty", Message_Fail);
|
||||||
|
return TopoDS_Shape();
|
||||||
|
}
|
||||||
|
|
||||||
|
// now perform the translation
|
||||||
|
aReader.TransferRoots();
|
||||||
|
return aReader.OneShape();
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : open
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
bool OcctJni_Viewer::open (const TCollection_AsciiString& thePath)
|
||||||
|
{
|
||||||
|
myShape.Nullify();
|
||||||
|
if (!myContext.IsNull())
|
||||||
|
{
|
||||||
|
myContext->RemoveAll (Standard_False);
|
||||||
|
}
|
||||||
|
if (thePath.IsEmpty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSD_Timer aTimer;
|
||||||
|
aTimer.Start();
|
||||||
|
TCollection_AsciiString aFormatStr;
|
||||||
|
const Standard_Integer aLen = thePath.Length();
|
||||||
|
if (aLen >= 5
|
||||||
|
&& thePath.Value (aLen - 4) == '.')
|
||||||
|
{
|
||||||
|
aFormatStr = thePath.SubString (aLen - 3, aLen);
|
||||||
|
}
|
||||||
|
else if (aLen >= 4
|
||||||
|
&& thePath.Value (aLen - 3) == '.')
|
||||||
|
{
|
||||||
|
aFormatStr = thePath.SubString (aLen - 2, aLen);
|
||||||
|
}
|
||||||
|
else if (aLen >= 3
|
||||||
|
&& thePath.Value (aLen - 2) == '.')
|
||||||
|
{
|
||||||
|
aFormatStr = thePath.SubString (aLen - 1, aLen);
|
||||||
|
}
|
||||||
|
aFormatStr.LowerCase();
|
||||||
|
|
||||||
|
TopoDS_Shape aShape;
|
||||||
|
if (aFormatStr == "stp"
|
||||||
|
|| aFormatStr == "step")
|
||||||
|
{
|
||||||
|
aShape = loadSTEP (thePath);
|
||||||
|
}
|
||||||
|
else if (aFormatStr == "igs"
|
||||||
|
|| aFormatStr == "iges")
|
||||||
|
{
|
||||||
|
aShape = loadIGES (thePath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// if (aFormatStr == "brep"
|
||||||
|
// || aFormatStr == "rle")
|
||||||
|
{
|
||||||
|
BRep_Builder aBuilder;
|
||||||
|
if (!BRepTools::Read (aShape, thePath.ToCString(), aBuilder))
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send (TCollection_AsciiString() + "Error: file '" + thePath + "' can not be opened!", Message_Info);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (aShape.IsNull())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
aTimer.Stop();
|
||||||
|
Message::DefaultMessenger()->Send (TCollection_AsciiString() + "File '" + thePath + "' loaded in " + aTimer.ElapsedTime() + " seconds", Message_Info);
|
||||||
|
|
||||||
|
myShape = aShape;
|
||||||
|
if (myContext.IsNull())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
aTimer.Reset();
|
||||||
|
aTimer.Start();
|
||||||
|
|
||||||
|
Handle(AIS_Shape) aShapePrs = new AIS_Shape (aShape);
|
||||||
|
myContext->Display (aShapePrs, Standard_False);
|
||||||
|
myView->FitAll();
|
||||||
|
|
||||||
|
aTimer.Stop();
|
||||||
|
Message::DefaultMessenger()->Send (TCollection_AsciiString() + "Presentation computed in " + aTimer.ElapsedTime() + " seconds", Message_Info);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : saveSnapshot
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
bool OcctJni_Viewer::saveSnapshot (const TCollection_AsciiString& thePath,
|
||||||
|
int theWidth,
|
||||||
|
int theHeight)
|
||||||
|
{
|
||||||
|
if (myContext.IsNull()
|
||||||
|
|| thePath.IsEmpty())
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Image dump failed - view is unavailable", Message_Fail);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (theWidth < 1
|
||||||
|
|| theHeight < 1)
|
||||||
|
{
|
||||||
|
myView->Window()->Size (theWidth, theHeight);
|
||||||
|
}
|
||||||
|
if (theWidth < 1
|
||||||
|
|| theHeight < 1)
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send ("Image dump failed - view is unavailable", Message_Fail);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image_AlienPixMap anAlienImage;
|
||||||
|
if (!anAlienImage.InitTrash (Image_PixMap::ImgBGRA, theWidth, theHeight))
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send (TCollection_AsciiString() + "RGBA image " + theWidth + "x" + theHeight + " allocation failed", Message_Fail);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenGL ES does not support fetching data in BGRA format
|
||||||
|
// while FreeImage does not support RGBA format.
|
||||||
|
Image_PixMap anImage;
|
||||||
|
anImage.InitWrapper (Image_PixMap::ImgRGBA,
|
||||||
|
anAlienImage.ChangeData(),
|
||||||
|
anAlienImage.SizeX(),
|
||||||
|
anAlienImage.SizeY(),
|
||||||
|
anAlienImage.SizeRowBytes());
|
||||||
|
if (!myView->ToPixMap (anImage, theWidth, theHeight, Graphic3d_BT_RGBA))
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send (TCollection_AsciiString() + "View dump to the image " + theWidth + "x" + theHeight + " failed", Message_Fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Standard_Size aRow = 0; aRow < anAlienImage.SizeY(); ++aRow)
|
||||||
|
{
|
||||||
|
for (Standard_Size aCol = 0; aCol < anAlienImage.SizeX(); ++aCol)
|
||||||
|
{
|
||||||
|
Image_ColorRGBA& aPixel = anAlienImage.ChangeValue<Image_ColorRGBA> (aRow, aCol);
|
||||||
|
std::swap (aPixel.r(), aPixel.b());
|
||||||
|
//aPixel.a() = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!anAlienImage.Save (thePath))
|
||||||
|
{
|
||||||
|
Message::DefaultMessenger()->Send (TCollection_AsciiString() + "Image saving to path '" + thePath + "' failed", Message_Fail);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Message::DefaultMessenger()->Send (TCollection_AsciiString() + "View " + theWidth + "x" + theHeight + " dumped to image '" + thePath + "'", Message_Info);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : redraw
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
void OcctJni_Viewer::redraw()
|
||||||
|
{
|
||||||
|
if (myView.IsNull())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
myView->Redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : fitAll
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
void OcctJni_Viewer::fitAll()
|
||||||
|
{
|
||||||
|
if (myView.IsNull())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
myView->FitAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : startRotation
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
void OcctJni_Viewer::startRotation (int theStartX,
|
||||||
|
int theStartY)
|
||||||
|
{
|
||||||
|
if (myView.IsNull())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
myView->StartRotation (theStartX, theStartY, 0.45);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : onRotation
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
void OcctJni_Viewer::onRotation (int theX,
|
||||||
|
int theY)
|
||||||
|
{
|
||||||
|
if (myView.IsNull())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
myView->Rotation (theX, theY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : onPanning
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
void OcctJni_Viewer::onPanning (int theDX,
|
||||||
|
int theDY)
|
||||||
|
{
|
||||||
|
if (myView.IsNull())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
myView->Pan (theDX, theDY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : onClick
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
void OcctJni_Viewer::onClick (int theX,
|
||||||
|
int theY)
|
||||||
|
{
|
||||||
|
if (myView.IsNull())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
myContext->MoveTo (theX, theY, myView, Standard_False);
|
||||||
|
myContext->Select (Standard_True);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : stopAction
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
void OcctJni_Viewer::stopAction()
|
||||||
|
{
|
||||||
|
if (myView.IsNull())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define jexp extern "C" JNIEXPORT
|
||||||
|
|
||||||
|
jexp jlong JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppCreate (JNIEnv* theEnv,
|
||||||
|
jobject theObj)
|
||||||
|
{
|
||||||
|
return jlong(new OcctJni_Viewer());
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppDestroy (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr)
|
||||||
|
{
|
||||||
|
delete (OcctJni_Viewer* )theCppPtr;
|
||||||
|
|
||||||
|
Handle(Message_Messenger) aMsgMgr = Message::DefaultMessenger();
|
||||||
|
aMsgMgr->RemovePrinters (STANDARD_TYPE (OcctJni_MsgPrinter));
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppRelease (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->release();
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppInit (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr)
|
||||||
|
{
|
||||||
|
Handle(Message_Messenger) aMsgMgr = Message::DefaultMessenger();
|
||||||
|
aMsgMgr->RemovePrinters (STANDARD_TYPE (OcctJni_MsgPrinter));
|
||||||
|
aMsgMgr->AddPrinter (new OcctJni_MsgPrinter (theEnv, theObj));
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppResize (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr,
|
||||||
|
jint theWidth,
|
||||||
|
jint theHeight)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->resize (theWidth, theHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppOpen (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr,
|
||||||
|
jstring thePath)
|
||||||
|
{
|
||||||
|
const char* aPathPtr = theEnv->GetStringUTFChars (thePath, 0);
|
||||||
|
const TCollection_AsciiString aPath (aPathPtr);
|
||||||
|
theEnv->ReleaseStringUTFChars (thePath, aPathPtr);
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->open (aPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppRedraw (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetAxoProj (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->setProj (V3d_XposYnegZpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetXposProj (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Xpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetYposProj (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Ypos);
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetZposProj (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Zpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetXnegProj (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Xneg);
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetYnegProj (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Yneg);
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppSetZnegProj (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->setProj (V3d_Zneg);
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppFitAll (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->fitAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppStartRotation (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr,
|
||||||
|
jint theStartX,
|
||||||
|
jint theStartY)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->startRotation (theStartX, theStartY);
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppOnRotation (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr,
|
||||||
|
jint theX,
|
||||||
|
jint theY)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->onRotation (theX, theY);
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppOnPanning (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr,
|
||||||
|
jint theDX,
|
||||||
|
jint theDY)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->onPanning (theDX, theDY);
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppOnClick (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr,
|
||||||
|
jint theX,
|
||||||
|
jint theY)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->onClick (theX, theY);
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp void JNICALL Java_com_opencascade_jnisample_OcctJniRenderer_cppStopAction (JNIEnv* theEnv,
|
||||||
|
jobject theObj,
|
||||||
|
jlong theCppPtr)
|
||||||
|
{
|
||||||
|
((OcctJni_Viewer* )theCppPtr)->stopAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp jlong JNICALL Java_com_opencascade_jnisample_OcctJniActivity_cppOcctMajorVersion (JNIEnv* theEnv,
|
||||||
|
jobject theObj)
|
||||||
|
{
|
||||||
|
return OCC_VERSION_MAJOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp jlong JNICALL Java_com_opencascade_jnisample_OcctJniActivity_cppOcctMinorVersion (JNIEnv* theEnv,
|
||||||
|
jobject theObj)
|
||||||
|
{
|
||||||
|
return OCC_VERSION_MINOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
jexp jlong JNICALL Java_com_opencascade_jnisample_OcctJniActivity_cppOcctMicroVersion (JNIEnv* theEnv,
|
||||||
|
jobject theObj)
|
||||||
|
{
|
||||||
|
return OCC_VERSION_MAINTENANCE;
|
||||||
|
}
|
88
samples/java/jniviewer/jni/OcctJni_Viewer.hxx
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// Copyright (c) 2014 OPEN CASCADE SAS
|
||||||
|
//
|
||||||
|
// This file is part of Open CASCADE Technology software library.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||||
|
// by the Free Software Foundation, with special exception defined in the file
|
||||||
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||||
|
// distribution for complete text of the license and disclaimer of any warranty.
|
||||||
|
//
|
||||||
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||||
|
// commercial license or contractual agreement.
|
||||||
|
|
||||||
|
#include <OcctJni_Window.hxx>
|
||||||
|
|
||||||
|
#include <AIS_InteractiveContext.hxx>
|
||||||
|
#include <TopoDS_Shape.hxx>
|
||||||
|
#include <V3d_Viewer.hxx>
|
||||||
|
#include <V3d_View.hxx>
|
||||||
|
|
||||||
|
//! Main C++ back-end for activity.
|
||||||
|
class OcctJni_Viewer
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Empty constructor
|
||||||
|
OcctJni_Viewer();
|
||||||
|
|
||||||
|
//! Initialize the viewer
|
||||||
|
bool init();
|
||||||
|
|
||||||
|
//! Release the viewer
|
||||||
|
void release();
|
||||||
|
|
||||||
|
//! Resize the viewer
|
||||||
|
void resize (int theWidth,
|
||||||
|
int theHeight);
|
||||||
|
|
||||||
|
//! Open CAD file
|
||||||
|
bool open (const TCollection_AsciiString& thePath);
|
||||||
|
|
||||||
|
//! Take snapshot
|
||||||
|
bool saveSnapshot (const TCollection_AsciiString& thePath,
|
||||||
|
int theWidth = 0,
|
||||||
|
int theHeight = 0);
|
||||||
|
|
||||||
|
//! Viewer update.
|
||||||
|
void redraw();
|
||||||
|
|
||||||
|
//! Move camera
|
||||||
|
void setProj (V3d_TypeOfOrientation theProj) { if (!myView.IsNull()) myView->SetProj (theProj); }
|
||||||
|
|
||||||
|
//! Fit All.
|
||||||
|
void fitAll();
|
||||||
|
|
||||||
|
//! Start rotation (remember first point position)
|
||||||
|
void startRotation (int theStartX,
|
||||||
|
int theStartY);
|
||||||
|
|
||||||
|
//! Perform rotation (relative to first point)
|
||||||
|
void onRotation (int theX,
|
||||||
|
int theY);
|
||||||
|
|
||||||
|
//! Perform panning
|
||||||
|
void onPanning (int theDX,
|
||||||
|
int theDY);
|
||||||
|
|
||||||
|
//! Perform selection
|
||||||
|
void onClick (int theX,
|
||||||
|
int theY);
|
||||||
|
|
||||||
|
//! Stop previously started action
|
||||||
|
void stopAction();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
//! Reset viewer content.
|
||||||
|
void initContent();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Handle(V3d_Viewer) myViewer;
|
||||||
|
Handle(V3d_View) myView;
|
||||||
|
Handle(AIS_InteractiveContext) myContext;
|
||||||
|
TopoDS_Shape myShape;
|
||||||
|
|
||||||
|
};
|
17
samples/java/jniviewer/jni/OcctJni_Window.cxx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (c) 2014 OPEN CASCADE SAS
|
||||||
|
//
|
||||||
|
// This file is part of Open CASCADE Technology software library.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||||
|
// by the Free Software Foundation, with special exception defined in the file
|
||||||
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||||
|
// distribution for complete text of the license and disclaimer of any warranty.
|
||||||
|
//
|
||||||
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||||
|
// commercial license or contractual agreement.
|
||||||
|
|
||||||
|
#include <OcctJni_Window.hxx>
|
||||||
|
|
||||||
|
IMPLEMENT_STANDARD_HANDLE (OcctJni_Window, Aspect_Window)
|
||||||
|
IMPLEMENT_STANDARD_RTTIEXT(OcctJni_Window, Aspect_Window)
|
106
samples/java/jniviewer/jni/OcctJni_Window.hxx
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// Copyright (c) 2014 OPEN CASCADE SAS
|
||||||
|
//
|
||||||
|
// This file is part of Open CASCADE Technology software library.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||||
|
// by the Free Software Foundation, with special exception defined in the file
|
||||||
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||||
|
// distribution for complete text of the license and disclaimer of any warranty.
|
||||||
|
//
|
||||||
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||||
|
// commercial license or contractual agreement.
|
||||||
|
|
||||||
|
#ifndef OcctJni_Window_H
|
||||||
|
#define OcctJni_Window_H
|
||||||
|
|
||||||
|
#include <Aspect_Window.hxx>
|
||||||
|
|
||||||
|
//! This class defines dummy window
|
||||||
|
class OcctJni_Window : public Aspect_Window
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Creates a wrapper over existing Window handle
|
||||||
|
OcctJni_Window (const int theWidth, const int theHeight)
|
||||||
|
: myWidth (theWidth), myHeight(theHeight) {}
|
||||||
|
|
||||||
|
//! Returns native Window handle
|
||||||
|
virtual Aspect_Drawable NativeHandle() const { return 0; }
|
||||||
|
|
||||||
|
//! Returns parent of native Window handle
|
||||||
|
virtual Aspect_Drawable NativeParentHandle() const { return 0; }
|
||||||
|
|
||||||
|
virtual void Destroy() {}
|
||||||
|
|
||||||
|
//! Opens the window <me>
|
||||||
|
virtual void Map() const {}
|
||||||
|
|
||||||
|
//! Closes the window <me>
|
||||||
|
virtual void Unmap() const {}
|
||||||
|
|
||||||
|
//! Applies the resizing to the window <me>
|
||||||
|
virtual Aspect_TypeOfResize DoResize() const { return Aspect_TOR_UNKNOWN; }
|
||||||
|
|
||||||
|
//! Apply the mapping change to the window <me>
|
||||||
|
virtual Standard_Boolean DoMapping() const { return Standard_True; }
|
||||||
|
|
||||||
|
//! Returns True if the window <me> is opened
|
||||||
|
virtual Standard_Boolean IsMapped() const { return Standard_True; }
|
||||||
|
|
||||||
|
//! Returns The Window RATIO equal to the physical WIDTH/HEIGHT dimensions
|
||||||
|
virtual Quantity_Ratio Ratio() const { return 1.0; }
|
||||||
|
|
||||||
|
//! Returns The Window POSITION in PIXEL
|
||||||
|
virtual void Position (Standard_Integer& theX1,
|
||||||
|
Standard_Integer& theY1,
|
||||||
|
Standard_Integer& theX2,
|
||||||
|
Standard_Integer& theY2) const
|
||||||
|
{
|
||||||
|
theX1 = 0;
|
||||||
|
theX2 = myWidth;
|
||||||
|
theY1 = 0;
|
||||||
|
theY2 = myHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Set The Window POSITION in PIXEL
|
||||||
|
virtual void SetPosition (const Standard_Integer theX1,
|
||||||
|
const Standard_Integer theY1,
|
||||||
|
const Standard_Integer theX2,
|
||||||
|
const Standard_Integer theY2)
|
||||||
|
{
|
||||||
|
myWidth = theX2 - theX1;
|
||||||
|
myHeight = theY2 - theY1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns The Window SIZE in PIXEL
|
||||||
|
virtual void Size (Standard_Integer& theWidth,
|
||||||
|
Standard_Integer& theHeight) const
|
||||||
|
{
|
||||||
|
theWidth = myWidth;
|
||||||
|
theHeight = myHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Set The Window SIZE in PIXEL
|
||||||
|
virtual void SetSize (const Standard_Integer theWidth,
|
||||||
|
const Standard_Integer theHeight)
|
||||||
|
{
|
||||||
|
myWidth = theWidth;
|
||||||
|
myHeight = theHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
int myWidth;
|
||||||
|
int myHeight;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DEFINE_STANDARD_RTTI(OcctJni_Window)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_STANDARD_HANDLE(OcctJni_Window, Aspect_Window)
|
||||||
|
|
||||||
|
#endif // OcctJni_Window_H
|
14
samples/java/jniviewer/project.properties
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system edit
|
||||||
|
# "ant.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
#
|
||||||
|
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||||
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
|
# Project target.
|
||||||
|
target=android-15
|
BIN
samples/java/jniviewer/res/drawable-hdpi/close_l.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
samples/java/jniviewer/res/drawable-hdpi/close_p.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
samples/java/jniviewer/res/drawable-hdpi/fit.png
Normal file
After Width: | Height: | Size: 1002 B |
BIN
samples/java/jniviewer/res/drawable-hdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
BIN
samples/java/jniviewer/res/drawable-hdpi/info.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
samples/java/jniviewer/res/drawable-hdpi/info_image.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
samples/java/jniviewer/res/drawable-hdpi/message.png
Normal file
After Width: | Height: | Size: 443 B |
BIN
samples/java/jniviewer/res/drawable-hdpi/open.png
Normal file
After Width: | Height: | Size: 917 B |
BIN
samples/java/jniviewer/res/drawable-hdpi/open_l.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
samples/java/jniviewer/res/drawable-hdpi/open_p.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
samples/java/jniviewer/res/drawable-hdpi/proj_back.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
samples/java/jniviewer/res/drawable-hdpi/proj_bottom.png
Executable file
After Width: | Height: | Size: 1.8 KiB |
BIN
samples/java/jniviewer/res/drawable-hdpi/proj_front.png
Executable file
After Width: | Height: | Size: 1.6 KiB |
BIN
samples/java/jniviewer/res/drawable-hdpi/proj_left.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
samples/java/jniviewer/res/drawable-hdpi/proj_right.png
Executable file
After Width: | Height: | Size: 1.6 KiB |
BIN
samples/java/jniviewer/res/drawable-hdpi/proj_top.png
Executable file
After Width: | Height: | Size: 1.8 KiB |
BIN
samples/java/jniviewer/res/drawable-hdpi/view.png
Normal file
After Width: | Height: | Size: 839 B |
BIN
samples/java/jniviewer/res/drawable-mdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 1.6 KiB |
BIN
samples/java/jniviewer/res/drawable-xhdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 3.6 KiB |
BIN
samples/java/jniviewer/res/drawable-xxhdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 5.4 KiB |
166
samples/java/jniviewer/res/layout/activity_main.xml
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/panel_main"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:stretchColumns="1">
|
||||||
|
|
||||||
|
<LinearLayout android:layout_height="fill_parent"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:id="@+id/linearLayout2">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/submenu_group"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent" >
|
||||||
|
|
||||||
|
<com.opencascade.jnisample.OcctJniView
|
||||||
|
android:id="@+id/custom_view"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_gravity="bottom|end" >
|
||||||
|
</com.opencascade.jnisample.OcctJniView>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/scroll_btn"
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@null"
|
||||||
|
android:src="@drawable/close_p" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/panel_menu"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal" >
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/open"
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight=".2"
|
||||||
|
android:background="@color/btnColor"
|
||||||
|
android:src="@drawable/open" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/fit"
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight=".2"
|
||||||
|
android:background="@color/btnColor"
|
||||||
|
android:src="@drawable/fit" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/view"
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight=".2"
|
||||||
|
android:background="@color/btnColor"
|
||||||
|
android:src="@drawable/view" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/info"
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight=".2"
|
||||||
|
android:background="@color/btnColor"
|
||||||
|
android:src="@drawable/info" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/message"
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight=".2"
|
||||||
|
android:background="@color/btnColor"
|
||||||
|
android:src="@drawable/message" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/message_view"
|
||||||
|
android:background="@color/viewColor"
|
||||||
|
android:text="Message Log"
|
||||||
|
android:textSize="16px"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/info_view"
|
||||||
|
android:background="@color/viewColor"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="info Log"
|
||||||
|
android:textSize="16px"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/view_group"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:background="@color/btnColor"
|
||||||
|
android:id="@+id/proj_front"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:src="@drawable/proj_front"
|
||||||
|
android:layout_weight=".16"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:background="@color/btnColor"
|
||||||
|
android:id="@+id/proj_top"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:src="@drawable/proj_top"
|
||||||
|
android:layout_weight=".16"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:background="@color/btnColor"
|
||||||
|
android:id="@+id/proj_left"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:src="@drawable/proj_left"
|
||||||
|
android:layout_weight=".16"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:background="@color/btnColor"
|
||||||
|
android:id="@+id/proj_back"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:src="@drawable/proj_back"
|
||||||
|
android:layout_weight=".16"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:background="@color/btnColor"
|
||||||
|
android:id="@+id/proj_bottom"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:src="@drawable/proj_bottom"
|
||||||
|
android:layout_weight=".16"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:background="@color/btnColor"
|
||||||
|
android:id="@+id/proj_right"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:src="@drawable/proj_right"
|
||||||
|
android:layout_weight=".16"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</TableLayout>
|
17
samples/java/jniviewer/res/values/id.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<item name="open" type="id"/>
|
||||||
|
<item name="save" type="id"/>
|
||||||
|
<item name="screenshot" type="id"/>
|
||||||
|
<item name="mesh_none" type="id"/>
|
||||||
|
<item name="mesh_low_q" type="id"/>
|
||||||
|
<item name="mesh_norm_q" type="id"/>
|
||||||
|
<item name="mesh_high_q" type="id"/>
|
||||||
|
<item name="view1" type="id"/>
|
||||||
|
<item name="view2" type="id"/>
|
||||||
|
<item name="view3" type="id"/>
|
||||||
|
<item name="settings" type="id"/>
|
||||||
|
<item name="message" type="id"/>
|
||||||
|
<item name="lock" type="id"/>
|
||||||
|
<item name="info" type="id"/>
|
||||||
|
</resources>
|
35
samples/java/jniviewer/res/values/strings.xml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">OpenCASCADE JNI Java Sample</string>
|
||||||
|
<color name="btnColor">#484848</color>
|
||||||
|
<color name="pressedBtnColor">#0099CC</color>
|
||||||
|
<color name="viewColor">#66252525</color>
|
||||||
|
<string-array name="ext_to_save">
|
||||||
|
<item>.png</item>
|
||||||
|
<item>.jpg</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="ext_to_exp">
|
||||||
|
<item>.brep</item>
|
||||||
|
<item>.rle</item>
|
||||||
|
<item>.iges</item>
|
||||||
|
<item>.igs</item>
|
||||||
|
<item>.step</item>
|
||||||
|
<item>.stp</item>
|
||||||
|
</string-array>
|
||||||
|
<string name="wireframe_shading_title">wireframe/shading</string>
|
||||||
|
<string name="color_title">color</string>
|
||||||
|
<string name="material_title">material</string>
|
||||||
|
<string name="transparency_title">transparency</string>
|
||||||
|
<string name="hidden_lines_title">show/hide hidden lines</string>
|
||||||
|
<string name="info_html" formatted="false">
|
||||||
|
<![CDATA[
|
||||||
|
<p>OpenCASCADE JNI Java Sample</p>
|
||||||
|
<p>Simple viewer for BREP, STEP and IGES files.</p>
|
||||||
|
<p>Driven by Open CASCADE Technology %d.%d.%d.</p>
|
||||||
|
<p>Copyright 2014 OPEN CASCADE SAS.</p>
|
||||||
|
<p><img src="info_image"></p>
|
||||||
|
<p>http://www.opencascade.com</p>
|
||||||
|
<p>http://www.opencascade.org</p>
|
||||||
|
]]>
|
||||||
|
</string>
|
||||||
|
</resources>
|
@ -0,0 +1,778 @@
|
|||||||
|
// Copyright (c) 2014 OPEN CASCADE SAS
|
||||||
|
//
|
||||||
|
// This file is part of Open CASCADE Technology software library.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||||
|
// by the Free Software Foundation, with special exception defined in the file
|
||||||
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||||
|
// distribution for complete text of the license and disclaimer of any warranty.
|
||||||
|
//
|
||||||
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||||
|
// commercial license or contractual agreement.
|
||||||
|
|
||||||
|
package com.opencascade.jnisample;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.Html.ImageGetter;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.Display;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.view.ViewGroup.LayoutParams;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
//! Main activity
|
||||||
|
public class OcctJniActivity extends Activity implements OnClickListener
|
||||||
|
{
|
||||||
|
|
||||||
|
//! Auxiliary method to print temporary info messages
|
||||||
|
public static void printShortInfo (Activity theActivity,
|
||||||
|
CharSequence theInfo)
|
||||||
|
{
|
||||||
|
Context aCtx = theActivity.getApplicationContext();
|
||||||
|
Toast aToast = Toast.makeText (aCtx, theInfo, Toast.LENGTH_LONG);
|
||||||
|
aToast.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Load single native library
|
||||||
|
private static boolean loadLibVerbose (String theLibName,
|
||||||
|
StringBuilder theLoadedInfo,
|
||||||
|
StringBuilder theFailedInfo)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
System.loadLibrary (theLibName);
|
||||||
|
theLoadedInfo.append ("Info: native library \"");
|
||||||
|
theLoadedInfo.append (theLibName);
|
||||||
|
theLoadedInfo.append ("\" has been loaded\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (java.lang.UnsatisfiedLinkError theError)
|
||||||
|
{
|
||||||
|
theFailedInfo.append ("Error: native library \"");
|
||||||
|
theFailedInfo.append (theLibName);
|
||||||
|
theFailedInfo.append ("\" is unavailable:\n " + theError.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (SecurityException theError)
|
||||||
|
{
|
||||||
|
theFailedInfo.append ("Error: native library \"");
|
||||||
|
theFailedInfo.append (theLibName);
|
||||||
|
theFailedInfo.append ("\" can not be loaded for security reasons:\n " + theError.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean wasNativesLoadCalled = false;
|
||||||
|
public static boolean areNativeLoaded = false;
|
||||||
|
public static String nativeLoaded = "";
|
||||||
|
public static String nativeFailed = "";
|
||||||
|
|
||||||
|
//! Auxiliary method to load native libraries
|
||||||
|
public boolean loadNatives()
|
||||||
|
{
|
||||||
|
if (wasNativesLoadCalled)
|
||||||
|
{
|
||||||
|
return areNativeLoaded;
|
||||||
|
}
|
||||||
|
wasNativesLoadCalled = true;
|
||||||
|
StringBuilder aLoaded = new StringBuilder();
|
||||||
|
StringBuilder aFailed = new StringBuilder();
|
||||||
|
|
||||||
|
// copy OCCT resources
|
||||||
|
String aResFolder = getFilesDir().getAbsolutePath();
|
||||||
|
copyAssetFolder (getAssets(), "Shaders", aResFolder + "/Shaders");
|
||||||
|
copyAssetFolder (getAssets(), "SHMessage", aResFolder + "/SHMessage");
|
||||||
|
copyAssetFolder (getAssets(), "XSMessage", aResFolder + "/XSMessage");
|
||||||
|
copyAssetFolder (getAssets(), "TObj", aResFolder + "/TObj");
|
||||||
|
copyAssetFolder (getAssets(), "UnitsAPI", aResFolder + "/UnitsAPI");
|
||||||
|
|
||||||
|
// C++ runtime
|
||||||
|
loadLibVerbose ("gnustl_shared", aLoaded, aFailed);
|
||||||
|
|
||||||
|
// 3rd-parties
|
||||||
|
loadLibVerbose ("freetype", aLoaded, aFailed);
|
||||||
|
loadLibVerbose ("freeimage", aLoaded, aFailed);
|
||||||
|
|
||||||
|
if (// OCCT modeling
|
||||||
|
!loadLibVerbose ("TKernel", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKMath", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKG2d", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKG3d", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKGeomBase", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKBRep", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKGeomAlgo", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKTopAlgo", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKShHealing", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKMesh", aLoaded, aFailed)
|
||||||
|
// exchange
|
||||||
|
|| !loadLibVerbose ("TKPrim", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKBO", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKBool", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKFillet", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKOffset", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKXSBase", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKIGES", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKSTEPBase", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKSTEPAttr", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKSTEP209", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKSTEP", aLoaded, aFailed)
|
||||||
|
// OCCT Visualization
|
||||||
|
|| !loadLibVerbose ("TKService", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKHLR", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKV3d", aLoaded, aFailed)
|
||||||
|
|| !loadLibVerbose ("TKOpenGl", aLoaded, aFailed)
|
||||||
|
// application code
|
||||||
|
|| !loadLibVerbose ("TKJniSample", aLoaded, aFailed))
|
||||||
|
{
|
||||||
|
nativeLoaded = aLoaded.toString();
|
||||||
|
nativeFailed = aFailed.toString();
|
||||||
|
areNativeLoaded = false;
|
||||||
|
//exitWithError (theActivity, "Broken apk?\n" + theFailedInfo);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nativeLoaded = aLoaded.toString();
|
||||||
|
areNativeLoaded = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Create activity
|
||||||
|
@Override protected void onCreate (Bundle theBundle)
|
||||||
|
{
|
||||||
|
super.onCreate (theBundle);
|
||||||
|
|
||||||
|
boolean isLoaded = loadNatives();
|
||||||
|
if (!isLoaded)
|
||||||
|
{
|
||||||
|
printShortInfo (this, nativeFailed);
|
||||||
|
OcctJniLogger.postMessage (nativeLoaded + "\n" + nativeFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
setContentView (R.layout.activity_main);
|
||||||
|
|
||||||
|
myOcctView = (OcctJniView )findViewById (R.id.custom_view);
|
||||||
|
myMessageTextView = (TextView )findViewById (R.id.message_view);
|
||||||
|
OcctJniLogger.setTextView (myMessageTextView);
|
||||||
|
|
||||||
|
createViewAndButtons (Configuration.ORIENTATION_LANDSCAPE);
|
||||||
|
|
||||||
|
myButtonPreferSize = defineButtonSize ((LinearLayout )findViewById (R.id.panel_menu));
|
||||||
|
ImageButton aScrollBtn = (ImageButton )findViewById (R.id.scroll_btn);
|
||||||
|
aScrollBtn.setY (myButtonPreferSize);
|
||||||
|
aScrollBtn.setOnTouchListener (new View.OnTouchListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean onTouch (View theView, MotionEvent theEvent)
|
||||||
|
{
|
||||||
|
return onScrollBtnTouch (theView, theEvent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onConfigurationChanged (getResources().getConfiguration());
|
||||||
|
|
||||||
|
Intent anIntent = getIntent();
|
||||||
|
Uri aDataUrl = anIntent != null ? anIntent.getData() : null;
|
||||||
|
String aDataPath = aDataUrl != null ? aDataUrl.getPath() : "";
|
||||||
|
myOcctView.open (aDataPath);
|
||||||
|
myLastPath = aDataPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Handle scroll events
|
||||||
|
private boolean onScrollBtnTouch (View theView,
|
||||||
|
MotionEvent theEvent)
|
||||||
|
{
|
||||||
|
switch (theEvent.getAction())
|
||||||
|
{
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
{
|
||||||
|
LinearLayout aPanelMenu = (LinearLayout )findViewById (R.id.panel_menu);
|
||||||
|
boolean isLandscape = (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
|
||||||
|
if (aPanelMenu.getVisibility() == View.VISIBLE)
|
||||||
|
{
|
||||||
|
aPanelMenu.setVisibility (View.GONE);
|
||||||
|
if (!isLandscape)
|
||||||
|
{
|
||||||
|
((ImageButton )theView).setImageResource (R.drawable.open_p);
|
||||||
|
theView.setY (0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
((ImageButton )theView).setImageResource (R.drawable.open_l);
|
||||||
|
theView.setX (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aPanelMenu.setVisibility (View.VISIBLE);
|
||||||
|
if (!isLandscape)
|
||||||
|
{
|
||||||
|
((ImageButton )theView).setImageResource (R.drawable.close_p);
|
||||||
|
theView.setY (myButtonPreferSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
((ImageButton )theView).setImageResource (R.drawable.close_l);
|
||||||
|
theView.setX (myButtonPreferSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Initialize views and buttons
|
||||||
|
private void createViewAndButtons (int theOrientation)
|
||||||
|
{
|
||||||
|
// open button
|
||||||
|
ImageButton anOpenButton = (ImageButton )findViewById (R.id.open);
|
||||||
|
anOpenButton.setOnClickListener (this);
|
||||||
|
|
||||||
|
// fit all
|
||||||
|
ImageButton aFitAllButton = (ImageButton )findViewById (R.id.fit);
|
||||||
|
aFitAllButton.setOnClickListener (this);
|
||||||
|
aFitAllButton.setOnTouchListener (new View.OnTouchListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean onTouch (View theView, MotionEvent theEvent)
|
||||||
|
{
|
||||||
|
return onTouchButton (theView, theEvent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// message
|
||||||
|
ImageButton aMessageButton = (ImageButton )findViewById (R.id.message);
|
||||||
|
aMessageButton.setOnClickListener (this);
|
||||||
|
|
||||||
|
// info
|
||||||
|
ImageButton anInfoButton = (ImageButton )findViewById (R.id.info);
|
||||||
|
anInfoButton.setOnClickListener (this);
|
||||||
|
|
||||||
|
// font for text view
|
||||||
|
TextView anInfoView = (TextView )findViewById (R.id.info_view);
|
||||||
|
anInfoView.setTextSize (TypedValue.COMPLEX_UNIT_SP, 18);
|
||||||
|
|
||||||
|
// add submenu buttons
|
||||||
|
createSubmenuBtn (R.id.view, R.id.view_group,
|
||||||
|
Arrays.asList (R.id.proj_front, R.id.proj_top, R.id.proj_left,
|
||||||
|
R.id.proj_back, R.id.proj_bottom, R.id.proj_right),
|
||||||
|
Arrays.asList (R.drawable.proj_front, R.drawable.proj_top, R.drawable.proj_left,
|
||||||
|
R.drawable.proj_back, R.drawable.proj_bottom, R.drawable.proj_right),
|
||||||
|
4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override protected void onNewIntent (Intent theIntent)
|
||||||
|
{
|
||||||
|
super.onNewIntent (theIntent);
|
||||||
|
setIntent (theIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override protected void onDestroy()
|
||||||
|
{
|
||||||
|
super.onDestroy();
|
||||||
|
OcctJniLogger.setTextView (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override protected void onPause()
|
||||||
|
{
|
||||||
|
super.onPause();
|
||||||
|
myOcctView.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override protected void onResume()
|
||||||
|
{
|
||||||
|
super.onResume();
|
||||||
|
myOcctView.onResume();
|
||||||
|
|
||||||
|
Intent anIntent = getIntent();
|
||||||
|
Uri aDataUrl = anIntent != null ? anIntent.getData() : null;
|
||||||
|
String aDataPath = aDataUrl != null ? aDataUrl.getPath() : "";
|
||||||
|
if (!aDataPath.equals (myLastPath))
|
||||||
|
{
|
||||||
|
myOcctView.open (aDataPath);
|
||||||
|
myLastPath = aDataPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Copy folder from assets
|
||||||
|
private boolean copyAssetFolder (AssetManager theAssetMgr,
|
||||||
|
String theAssetFolder,
|
||||||
|
String theFolderPathTo)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String[] aFiles = theAssetMgr.list (theAssetFolder);
|
||||||
|
File aFolder = new File (theFolderPathTo);
|
||||||
|
aFolder.mkdirs();
|
||||||
|
boolean isOk = true;
|
||||||
|
for (String aFileIter : aFiles)
|
||||||
|
{
|
||||||
|
if (aFileIter.contains ("."))
|
||||||
|
{
|
||||||
|
isOk &= copyAsset (theAssetMgr,
|
||||||
|
theAssetFolder + "/" + aFileIter,
|
||||||
|
theFolderPathTo + "/" + aFileIter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isOk &= copyAssetFolder (theAssetMgr,
|
||||||
|
theAssetFolder + "/" + aFileIter,
|
||||||
|
theFolderPathTo + "/" + aFileIter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isOk;
|
||||||
|
}
|
||||||
|
catch (Exception theError)
|
||||||
|
{
|
||||||
|
theError.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Copy single file from assets
|
||||||
|
private boolean copyAsset (AssetManager theAssetMgr,
|
||||||
|
String thePathFrom,
|
||||||
|
String thePathTo)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InputStream aStreamIn = theAssetMgr.open (thePathFrom);
|
||||||
|
File aFileTo = new File (thePathTo);
|
||||||
|
aFileTo.createNewFile();
|
||||||
|
OutputStream aStreamOut = new FileOutputStream (thePathTo);
|
||||||
|
copyStreamContent (aStreamIn, aStreamOut);
|
||||||
|
aStreamIn.close();
|
||||||
|
aStreamIn = null;
|
||||||
|
aStreamOut.flush();
|
||||||
|
aStreamOut.close();
|
||||||
|
aStreamOut = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception theError)
|
||||||
|
{
|
||||||
|
theError.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Copy single file
|
||||||
|
private static void copyStreamContent (InputStream theIn,
|
||||||
|
OutputStream theOut) throws IOException
|
||||||
|
{
|
||||||
|
byte[] aBuffer = new byte[1024];
|
||||||
|
int aNbReadBytes = 0;
|
||||||
|
while ((aNbReadBytes = theIn.read (aBuffer)) != -1)
|
||||||
|
{
|
||||||
|
theOut.write (aBuffer, 0, aNbReadBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Show/hide text view
|
||||||
|
private void switchTextView (TextView theTextView,
|
||||||
|
ImageButton theClickedBtn,
|
||||||
|
boolean theToSwitchOn)
|
||||||
|
{
|
||||||
|
if (theTextView != null
|
||||||
|
&& theTextView.getVisibility() == View.GONE
|
||||||
|
&& theToSwitchOn)
|
||||||
|
{
|
||||||
|
theTextView.setVisibility (View.VISIBLE);
|
||||||
|
theClickedBtn.setBackgroundColor (getResources().getColor(R.color.pressedBtnColor));
|
||||||
|
setTextViewPosition (theTextView);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
theTextView.setVisibility (View.GONE);
|
||||||
|
theClickedBtn.setBackgroundColor (getResources().getColor (R.color.btnColor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Setup text view position
|
||||||
|
private void setTextViewPosition (TextView theTextView)
|
||||||
|
{
|
||||||
|
if (theTextView.getVisibility() != View.VISIBLE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
|
||||||
|
{
|
||||||
|
theTextView.setX (myButtonPreferSize);
|
||||||
|
theTextView.setY (0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
theTextView.setX (0);
|
||||||
|
theTextView.setY (myButtonPreferSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick (View theButton)
|
||||||
|
{
|
||||||
|
ImageButton aClickedBtn = (ImageButton )theButton;
|
||||||
|
switch (aClickedBtn.getId())
|
||||||
|
{
|
||||||
|
case R.id.message:
|
||||||
|
{
|
||||||
|
switchTextView ((TextView )findViewById (R.id.info_view),
|
||||||
|
(ImageButton )findViewById (R.id.info), false);
|
||||||
|
switchTextView (myMessageTextView, aClickedBtn, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case R.id.info:
|
||||||
|
{
|
||||||
|
String aText = getString (R.string.info_html);
|
||||||
|
aText = String.format (aText, cppOcctMajorVersion(), cppOcctMinorVersion(), cppOcctMicroVersion());
|
||||||
|
Spanned aSpanned = Html.fromHtml (aText, new ImageGetter()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Drawable getDrawable (String theSource)
|
||||||
|
{
|
||||||
|
Resources aResources = getResources();
|
||||||
|
int anId = aResources.getIdentifier (theSource, "drawable", getPackageName());
|
||||||
|
Drawable aRes = aResources.getDrawable (anId);
|
||||||
|
aRes.setBounds (0, 0, aRes.getIntrinsicWidth(), aRes.getIntrinsicHeight());
|
||||||
|
return aRes;
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
TextView anInfoView = (TextView )findViewById (R.id.info_view);
|
||||||
|
anInfoView.setText (aSpanned);
|
||||||
|
switchTextView (myMessageTextView, (ImageButton ) findViewById (R.id.message), false);
|
||||||
|
switchTextView (anInfoView, aClickedBtn, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case R.id.fit:
|
||||||
|
{
|
||||||
|
myOcctView.fitAll();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case R.id.proj_front:
|
||||||
|
{
|
||||||
|
myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Xpos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case R.id.proj_left:
|
||||||
|
{
|
||||||
|
myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Yneg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case R.id.proj_top:
|
||||||
|
{
|
||||||
|
myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Zpos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case R.id.proj_back:
|
||||||
|
{
|
||||||
|
myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Xneg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case R.id.proj_right:
|
||||||
|
{
|
||||||
|
myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Ypos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case R.id.proj_bottom:
|
||||||
|
{
|
||||||
|
myOcctView.setProj (OcctJniRenderer.TypeOfOrientation.Zneg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case R.id.open:
|
||||||
|
{
|
||||||
|
File aPath = Environment.getExternalStorageDirectory();
|
||||||
|
aClickedBtn.setBackgroundColor (getResources().getColor(R.color.pressedBtnColor));
|
||||||
|
if (myFileOpenDialog == null)
|
||||||
|
{
|
||||||
|
myFileOpenDialog = new OcctJniFileDialog (this, aPath);
|
||||||
|
myFileOpenDialog.setFileEndsWith (".brep");
|
||||||
|
myFileOpenDialog.setFileEndsWith (".rle");
|
||||||
|
myFileOpenDialog.setFileEndsWith (".iges");
|
||||||
|
myFileOpenDialog.setFileEndsWith (".igs");
|
||||||
|
myFileOpenDialog.setFileEndsWith (".step");
|
||||||
|
myFileOpenDialog.setFileEndsWith (".stp");
|
||||||
|
myFileOpenDialog.addFileListener (new OcctJniFileDialog.FileSelectedListener()
|
||||||
|
{
|
||||||
|
public void fileSelected (File theFile)
|
||||||
|
{
|
||||||
|
if (theFile != null && myOcctView != null)
|
||||||
|
{
|
||||||
|
myOcctView.open (theFile.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
myFileOpenDialog.addDialogDismissedListener (new OcctJniFileDialog.DialogDismissedListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void dialogDismissed()
|
||||||
|
{
|
||||||
|
ImageButton openButton = (ImageButton )findViewById (R.id.open);
|
||||||
|
openButton.setBackgroundColor (getResources().getColor(R.color.btnColor));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
myFileOpenDialog.showDialog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createSubmenuBtn (int theParentBtnId,
|
||||||
|
int theParentLayoutId,
|
||||||
|
final List<Integer> theNewButtonIds,
|
||||||
|
final List<Integer> theNewButtonImageIds,
|
||||||
|
int thePosition)
|
||||||
|
{
|
||||||
|
int aPosInList = 0;
|
||||||
|
final ImageButton aParentBtn = (ImageButton )findViewById (theParentBtnId);
|
||||||
|
|
||||||
|
ViewGroup.LayoutParams aParams = null;
|
||||||
|
LinearLayout parentLayout = (LinearLayout ) findViewById (theParentLayoutId);
|
||||||
|
for (Integer newButtonId : theNewButtonIds)
|
||||||
|
{
|
||||||
|
ImageButton aNewButton = (ImageButton )findViewById (newButtonId);
|
||||||
|
if (aNewButton == null)
|
||||||
|
{
|
||||||
|
aNewButton = (ImageButton )new ImageButton (this);
|
||||||
|
aNewButton.setId (newButtonId);
|
||||||
|
aNewButton.setImageResource (theNewButtonImageIds.get (aPosInList));
|
||||||
|
aNewButton.setLayoutParams (aParams);
|
||||||
|
parentLayout.addView (aNewButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
aNewButton.setOnClickListener (this);
|
||||||
|
aNewButton.setVisibility (View.GONE);
|
||||||
|
|
||||||
|
aNewButton.setOnTouchListener (new View.OnTouchListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean onTouch (View theView, MotionEvent theEvent)
|
||||||
|
{
|
||||||
|
return onTouchButton (theView, theEvent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
++aPosInList;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aParentBtn != null)
|
||||||
|
{
|
||||||
|
aParentBtn.setOnTouchListener (null);
|
||||||
|
aParentBtn.setOnTouchListener (new View.OnTouchListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean onTouch (View theView, MotionEvent theEvent)
|
||||||
|
{
|
||||||
|
if (theEvent.getAction () == MotionEvent.ACTION_DOWN)
|
||||||
|
{
|
||||||
|
Boolean isVisible = false;
|
||||||
|
for (Integer aNewButtonId : theNewButtonIds)
|
||||||
|
{
|
||||||
|
ImageButton anBtn = (ImageButton )findViewById (aNewButtonId);
|
||||||
|
if (anBtn != null)
|
||||||
|
{
|
||||||
|
if (anBtn.getVisibility() == View.GONE)
|
||||||
|
{
|
||||||
|
anBtn.setVisibility (View.VISIBLE);
|
||||||
|
isVisible = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
anBtn.setVisibility (View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aParentBtn.setBackgroundColor (!isVisible ? getResources().getColor(R.color.btnColor) : getResources().getColor(R.color.pressedBtnColor));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Implements onTouch functionality
|
||||||
|
private boolean onTouchButton (View theView,
|
||||||
|
MotionEvent theEvent)
|
||||||
|
{
|
||||||
|
switch (theEvent.getAction())
|
||||||
|
{
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
((ImageButton )theView).setBackgroundColor (getResources().getColor (R.color.pressedBtnColor));
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
((ImageButton )theView).setBackgroundColor (getResources().getColor (R.color.btnColor));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Handle configuration change event
|
||||||
|
@Override
|
||||||
|
public void onConfigurationChanged (Configuration theNewConfig)
|
||||||
|
{
|
||||||
|
super.onConfigurationChanged (theNewConfig);
|
||||||
|
LinearLayout aLayoutPanelMenu = (LinearLayout )findViewById (R.id.panel_menu);
|
||||||
|
LayoutParams aPanelMenuLayoutParams = aLayoutPanelMenu.getLayoutParams();
|
||||||
|
|
||||||
|
LinearLayout aLayoutViewGroup = (LinearLayout )findViewById (R.id.view_group);
|
||||||
|
LayoutParams aViewGroupLayoutParams = aLayoutViewGroup.getLayoutParams();
|
||||||
|
ImageButton aScrollBtn = (ImageButton )findViewById (R.id.scroll_btn);
|
||||||
|
LayoutParams aScrollBtnLayoutParams = aScrollBtn.getLayoutParams();
|
||||||
|
|
||||||
|
myButtonPreferSize = defineButtonSize ((LinearLayout )findViewById (R.id.panel_menu));
|
||||||
|
defineButtonSize ((LinearLayout )findViewById (R.id.view_group));
|
||||||
|
|
||||||
|
switch (theNewConfig.orientation)
|
||||||
|
{
|
||||||
|
case Configuration.ORIENTATION_PORTRAIT:
|
||||||
|
{
|
||||||
|
setHorizontal (aLayoutPanelMenu, aPanelMenuLayoutParams);
|
||||||
|
setHorizontal (aLayoutViewGroup, aViewGroupLayoutParams);
|
||||||
|
aLayoutViewGroup.setGravity (Gravity.BOTTOM);
|
||||||
|
|
||||||
|
aScrollBtnLayoutParams.height = LayoutParams.WRAP_CONTENT;
|
||||||
|
aScrollBtnLayoutParams.width = LayoutParams.MATCH_PARENT;
|
||||||
|
aScrollBtn.setLayoutParams (aScrollBtnLayoutParams);
|
||||||
|
if (aLayoutPanelMenu.getVisibility() == View.VISIBLE)
|
||||||
|
{
|
||||||
|
aScrollBtn.setImageResource (R.drawable.close_p);
|
||||||
|
aScrollBtn.setY (myButtonPreferSize);
|
||||||
|
aScrollBtn.setX (0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aScrollBtn.setImageResource (R.drawable.open_p);
|
||||||
|
aScrollBtn.setY (0);
|
||||||
|
aScrollBtn.setX (0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Configuration.ORIENTATION_LANDSCAPE:
|
||||||
|
{
|
||||||
|
setVertical (aLayoutPanelMenu, aPanelMenuLayoutParams);
|
||||||
|
setVertical (aLayoutViewGroup, aViewGroupLayoutParams);
|
||||||
|
aLayoutViewGroup.setGravity (Gravity.RIGHT);
|
||||||
|
|
||||||
|
aScrollBtnLayoutParams.height = LayoutParams.MATCH_PARENT;
|
||||||
|
aScrollBtnLayoutParams.width = LayoutParams.WRAP_CONTENT;
|
||||||
|
aScrollBtn.setLayoutParams (aScrollBtnLayoutParams);
|
||||||
|
if (aLayoutPanelMenu.getVisibility() == View.VISIBLE)
|
||||||
|
{
|
||||||
|
aScrollBtn.setImageResource (R.drawable.close_l);
|
||||||
|
aScrollBtn.setX (myButtonPreferSize);
|
||||||
|
aScrollBtn.setY (0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aScrollBtn.setImageResource (R.drawable.open_l);
|
||||||
|
aScrollBtn.setY (0);
|
||||||
|
aScrollBtn.setX (0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTextViewPosition (myMessageTextView);
|
||||||
|
setTextViewPosition ((TextView )findViewById (R.id.info_view));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setHorizontal (LinearLayout theLayout,
|
||||||
|
LayoutParams theLayoutParams)
|
||||||
|
{
|
||||||
|
theLayout.setOrientation (LinearLayout.HORIZONTAL);
|
||||||
|
theLayoutParams.height = LayoutParams.WRAP_CONTENT;
|
||||||
|
theLayoutParams.width = LayoutParams.MATCH_PARENT;
|
||||||
|
theLayout.setLayoutParams (theLayoutParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setVertical (LinearLayout theLayout,
|
||||||
|
LayoutParams theLayoutParams)
|
||||||
|
{
|
||||||
|
theLayout.setOrientation (LinearLayout.VERTICAL);
|
||||||
|
theLayoutParams.height = LayoutParams.MATCH_PARENT;
|
||||||
|
theLayoutParams.width = LayoutParams.WRAP_CONTENT;
|
||||||
|
theLayout.setLayoutParams (theLayoutParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Define button size
|
||||||
|
private int defineButtonSize (LinearLayout theLayout)
|
||||||
|
{
|
||||||
|
boolean isLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
|
||||||
|
Display aDisplay = getWindowManager().getDefaultDisplay();
|
||||||
|
Point aDispPnt = new Point();
|
||||||
|
aDisplay.getSize (aDispPnt);
|
||||||
|
|
||||||
|
int aNbChildren = theLayout.getChildCount();
|
||||||
|
int aHeight = aDispPnt.y / aNbChildren;
|
||||||
|
int aWidth = aDispPnt.x / aNbChildren;
|
||||||
|
int aResultSize = 0;
|
||||||
|
for (int aChildIter = 0; aChildIter < aNbChildren; ++aChildIter)
|
||||||
|
{
|
||||||
|
View aView = theLayout.getChildAt (aChildIter);
|
||||||
|
if (aView instanceof ImageButton)
|
||||||
|
{
|
||||||
|
ImageButton aButton = (ImageButton )aView;
|
||||||
|
if (isLandscape)
|
||||||
|
{
|
||||||
|
aButton.setMinimumWidth (aHeight);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aButton.setMinimumHeight (aWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isLandscape)
|
||||||
|
{
|
||||||
|
aResultSize = aHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aResultSize = aWidth;
|
||||||
|
}
|
||||||
|
return aResultSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! OCCT major version
|
||||||
|
private native long cppOcctMajorVersion();
|
||||||
|
|
||||||
|
//! OCCT minor version
|
||||||
|
private native long cppOcctMinorVersion();
|
||||||
|
|
||||||
|
//! OCCT micro version
|
||||||
|
private native long cppOcctMicroVersion();
|
||||||
|
|
||||||
|
private OcctJniView myOcctView;
|
||||||
|
private TextView myMessageTextView;
|
||||||
|
private String myLastPath;
|
||||||
|
private OcctJniFileDialog myFileOpenDialog;
|
||||||
|
private int myButtonPreferSize = 65;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,376 @@
|
|||||||
|
// Copyright (c) 2014 OPEN CASCADE SAS
|
||||||
|
//
|
||||||
|
// This file is part of Open CASCADE Technology software library.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||||
|
// by the Free Software Foundation, with special exception defined in the file
|
||||||
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||||
|
// distribution for complete text of the license and disclaimer of any warranty.
|
||||||
|
//
|
||||||
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||||
|
// commercial license or contractual agreement.
|
||||||
|
|
||||||
|
package com.opencascade.jnisample;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FilenameFilter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.opencascade.jnisample.ListenerList.FireHandler;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup.LayoutParams;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
//! Simple open file dialog
|
||||||
|
public class OcctJniFileDialog
|
||||||
|
{
|
||||||
|
|
||||||
|
public enum DialogMode
|
||||||
|
{
|
||||||
|
FileOpen, FileExport, FileSave
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String PARENT_DIR = "..";
|
||||||
|
private String[] myFileList;
|
||||||
|
private File myCurrentPath;
|
||||||
|
private DialogMode myDialogMode = DialogMode.FileOpen;
|
||||||
|
|
||||||
|
private ListenerList<FileSelectedListener> myFileListenerList = new ListenerList<OcctJniFileDialog.FileSelectedListener>();
|
||||||
|
private ListenerList<DialogDismissedListener> myDialogDismissedList = new ListenerList<DialogDismissedListener>();
|
||||||
|
private final Activity myActivity;
|
||||||
|
private List<String> myFileEndsWith;
|
||||||
|
private EditText myFileNameInput;
|
||||||
|
private Spinner myFileExtSpinner;
|
||||||
|
int myCurrentExtPositionInList = 0;
|
||||||
|
|
||||||
|
public interface FileSelectedListener
|
||||||
|
{
|
||||||
|
void fileSelected (File theFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface DialogDismissedListener
|
||||||
|
{
|
||||||
|
void dialogDismissed();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Main constructor.
|
||||||
|
public OcctJniFileDialog (Activity theActivity,
|
||||||
|
File thePath)
|
||||||
|
{
|
||||||
|
myActivity = theActivity;
|
||||||
|
if (!thePath.exists())
|
||||||
|
{
|
||||||
|
thePath = Environment.getExternalStorageDirectory();
|
||||||
|
}
|
||||||
|
loadFileList (thePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Create new dialog
|
||||||
|
public Dialog createFileDialog()
|
||||||
|
{
|
||||||
|
final Object[] anObjWrapper = new Object[1];
|
||||||
|
Dialog aDialog = null;
|
||||||
|
AlertDialog.Builder aBuilder = new AlertDialog.Builder (myActivity);
|
||||||
|
|
||||||
|
aBuilder.setTitle (myCurrentPath.getPath());
|
||||||
|
LinearLayout aTitleLayout = new LinearLayout (myActivity);
|
||||||
|
aTitleLayout.setLayoutParams (new LinearLayout.LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
|
||||||
|
aTitleLayout.setOrientation (LinearLayout.VERTICAL);
|
||||||
|
|
||||||
|
ListView list = new ListView (myActivity);
|
||||||
|
list.setScrollingCacheEnabled(false);
|
||||||
|
list.setBackgroundColor (Color.parseColor ("#33B5E5"));
|
||||||
|
|
||||||
|
list.setAdapter (new ArrayAdapter<String> (myActivity, android.R.layout.select_dialog_item, myFileList));
|
||||||
|
list.setOnItemClickListener (new AdapterView.OnItemClickListener ()
|
||||||
|
{
|
||||||
|
|
||||||
|
public void onItemClick (AdapterView<?> arg0, View view, int pos, long id)
|
||||||
|
{
|
||||||
|
String fileChosen = myFileList[pos];
|
||||||
|
File aChosenFile = getChosenFile (fileChosen);
|
||||||
|
if (aChosenFile.isDirectory())
|
||||||
|
{
|
||||||
|
loadFileList (aChosenFile);
|
||||||
|
((Dialog )anObjWrapper[0]).cancel();
|
||||||
|
((Dialog )anObjWrapper[0]).dismiss();
|
||||||
|
showDialog();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (myDialogMode == DialogMode.FileOpen)
|
||||||
|
{
|
||||||
|
((Dialog )anObjWrapper[0]).cancel();
|
||||||
|
((Dialog )anObjWrapper[0]).dismiss();
|
||||||
|
fireFileSelectedEvent (aChosenFile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
myFileNameInput.setText (aChosenFile.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
list.setLayoutParams (new LinearLayout.LayoutParams (LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 0.6f));
|
||||||
|
aTitleLayout.addView (list);
|
||||||
|
|
||||||
|
if (myDialogMode == DialogMode.FileSave
|
||||||
|
|| myDialogMode == DialogMode.FileExport)
|
||||||
|
{
|
||||||
|
myFileNameInput = new EditText (myActivity);
|
||||||
|
myFileExtSpinner = new Spinner (myActivity);
|
||||||
|
ArrayAdapter<CharSequence> adapter = null;
|
||||||
|
if (myDialogMode == DialogMode.FileExport)
|
||||||
|
{
|
||||||
|
adapter = ArrayAdapter.createFromResource (myActivity, R.array.ext_to_exp,
|
||||||
|
android.R.layout.simple_spinner_item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
adapter = ArrayAdapter.createFromResource (myActivity, R.array.ext_to_save,
|
||||||
|
android.R.layout.simple_spinner_item);
|
||||||
|
}
|
||||||
|
// Specify the layout to use when the list of choices appears
|
||||||
|
adapter.setDropDownViewResource (android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
// Apply the adapter to the spinner
|
||||||
|
myFileExtSpinner.setAdapter (adapter);
|
||||||
|
myFileExtSpinner.setSelection (myCurrentExtPositionInList);
|
||||||
|
|
||||||
|
myFileExtSpinner.setOnItemSelectedListener (new AdapterView.OnItemSelectedListener()
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected (AdapterView<?> theParentView)
|
||||||
|
{
|
||||||
|
// your code here
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemSelected (AdapterView<?> theParent, View theView, int thePosition, long theId)
|
||||||
|
{
|
||||||
|
if (myCurrentExtPositionInList != thePosition)
|
||||||
|
{
|
||||||
|
myCurrentExtPositionInList = thePosition;
|
||||||
|
setFileEndsWith (Arrays.asList (myFileExtSpinner.getSelectedItem().toString()));
|
||||||
|
loadFileList (myCurrentPath);
|
||||||
|
((Dialog )anObjWrapper[0]).cancel();
|
||||||
|
((Dialog )anObjWrapper[0]).dismiss();
|
||||||
|
showDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
myFileExtSpinner.setLayoutParams (new LinearLayout.LayoutParams (LayoutParams.MATCH_PARENT,
|
||||||
|
LayoutParams.WRAP_CONTENT, 0.2f));
|
||||||
|
// titleLayout.addView(fileExtSpinner);
|
||||||
|
myFileNameInput.setLayoutParams (new LinearLayout.LayoutParams (LayoutParams.MATCH_PARENT,
|
||||||
|
LayoutParams.WRAP_CONTENT, 0.2f));
|
||||||
|
LinearLayout aControlsView = new LinearLayout (myActivity);
|
||||||
|
|
||||||
|
aControlsView.addView (myFileNameInput);
|
||||||
|
aControlsView.addView (myFileExtSpinner);
|
||||||
|
|
||||||
|
aTitleLayout.addView (aControlsView);
|
||||||
|
aBuilder.setView (aTitleLayout);
|
||||||
|
aBuilder.setPositiveButton ("OK", new DialogInterface.OnClickListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onClick (DialogInterface theDialog, int theWhich)
|
||||||
|
{
|
||||||
|
if (theWhich >= 0)
|
||||||
|
{
|
||||||
|
String aFileChosen = myFileList[theWhich];
|
||||||
|
File aChosenFile = getChosenFile (aFileChosen);
|
||||||
|
fireFileSelectedEvent (aChosenFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).setNegativeButton ("Cancel", null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aBuilder.setNegativeButton ("Cancel", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
aBuilder.setView (aTitleLayout);
|
||||||
|
|
||||||
|
aDialog = aBuilder.show();
|
||||||
|
aDialog.setOnDismissListener (new DialogInterface.OnDismissListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onDismiss (DialogInterface theDialog)
|
||||||
|
{
|
||||||
|
fireDialogDismissedEvent();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
anObjWrapper[0] = aDialog;
|
||||||
|
return aDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFileListener (FileSelectedListener theListener)
|
||||||
|
{
|
||||||
|
myFileListenerList.add (theListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addDialogDismissedListener (DialogDismissedListener theListener)
|
||||||
|
{
|
||||||
|
myDialogDismissedList.add (theListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Show file dialog
|
||||||
|
public void showDialog()
|
||||||
|
{
|
||||||
|
createFileDialog().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fireFileSelectedEvent (final File theFile)
|
||||||
|
{
|
||||||
|
myFileListenerList.fireEvent (new FireHandler<OcctJniFileDialog.FileSelectedListener>()
|
||||||
|
{
|
||||||
|
public void fireEvent (FileSelectedListener theListener)
|
||||||
|
{
|
||||||
|
theListener.fileSelected (theFile);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fireDialogDismissedEvent()
|
||||||
|
{
|
||||||
|
myDialogDismissedList.fireEvent (new FireHandler<OcctJniFileDialog.DialogDismissedListener>()
|
||||||
|
{
|
||||||
|
public void fireEvent (DialogDismissedListener theListener)
|
||||||
|
{
|
||||||
|
theListener.dialogDismissed();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadFileList (File thePath)
|
||||||
|
{
|
||||||
|
myCurrentPath = thePath;
|
||||||
|
List<String> aList = new ArrayList<String>();
|
||||||
|
if (thePath.exists())
|
||||||
|
{
|
||||||
|
if (thePath.getParentFile() != null)
|
||||||
|
{
|
||||||
|
aList.add (PARENT_DIR);
|
||||||
|
}
|
||||||
|
FilenameFilter aFilter = new FilenameFilter()
|
||||||
|
{
|
||||||
|
public boolean accept (File theDir, String theFilename)
|
||||||
|
{
|
||||||
|
File aSel = new File (theDir, theFilename);
|
||||||
|
if (!aSel.canRead())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean isEndWith = false;
|
||||||
|
if (myFileEndsWith != null)
|
||||||
|
{
|
||||||
|
for (String aFileExtIter : myFileEndsWith)
|
||||||
|
{
|
||||||
|
if (theFilename.toLowerCase().endsWith (aFileExtIter))
|
||||||
|
{
|
||||||
|
isEndWith = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isEndWith || aSel.isDirectory();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
String[] aFileList1 = thePath.list (aFilter);
|
||||||
|
if (aFileList1 != null)
|
||||||
|
{
|
||||||
|
for (String aFileIter : aFileList1)
|
||||||
|
{
|
||||||
|
aList.add (aFileIter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
myFileList = (String[] )aList.toArray (new String[] {});
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getChosenFile (String theFileChosen)
|
||||||
|
{
|
||||||
|
if (theFileChosen.equals (PARENT_DIR))
|
||||||
|
return myCurrentPath.getParentFile();
|
||||||
|
else
|
||||||
|
return new File (myCurrentPath, theFileChosen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileEndsWith (String fileEndsWith)
|
||||||
|
{
|
||||||
|
if (myFileEndsWith == null)
|
||||||
|
{
|
||||||
|
myFileEndsWith = new ArrayList<String>();
|
||||||
|
}
|
||||||
|
if (myFileEndsWith.indexOf (fileEndsWith) == -1)
|
||||||
|
{
|
||||||
|
myFileEndsWith.add (fileEndsWith);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileEndsWith (List<String> theFileEndsWith)
|
||||||
|
{
|
||||||
|
myFileEndsWith = theFileEndsWith;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogMode DialogMode()
|
||||||
|
{
|
||||||
|
return myDialogMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DialogMode (DialogMode theMode)
|
||||||
|
{
|
||||||
|
myDialogMode = theMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ListenerList<L>
|
||||||
|
{
|
||||||
|
private List<L> myListenerList = new ArrayList<L>();
|
||||||
|
|
||||||
|
public interface FireHandler<L>
|
||||||
|
{
|
||||||
|
void fireEvent (L theListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add (L theListener)
|
||||||
|
{
|
||||||
|
myListenerList.add (theListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fireEvent (FireHandler<L> theFireHandler)
|
||||||
|
{
|
||||||
|
List<L> aCopy = new ArrayList<L> (myListenerList);
|
||||||
|
for (L anIter : aCopy)
|
||||||
|
{
|
||||||
|
theFireHandler.fireEvent (anIter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove (L theListener)
|
||||||
|
{
|
||||||
|
myListenerList.remove (theListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<L> getListenerList()
|
||||||
|
{
|
||||||
|
return myListenerList;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright (c) 2014 OPEN CASCADE SAS
|
||||||
|
//
|
||||||
|
// This file is part of Open CASCADE Technology software library.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||||
|
// by the Free Software Foundation, with special exception defined in the file
|
||||||
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||||
|
// distribution for complete text of the license and disclaimer of any warranty.
|
||||||
|
//
|
||||||
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||||
|
// commercial license or contractual agreement.
|
||||||
|
|
||||||
|
package com.opencascade.jnisample;
|
||||||
|
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
//! Auxiliary class for logging messages
|
||||||
|
public class OcctJniLogger
|
||||||
|
{
|
||||||
|
|
||||||
|
//! Setup text view
|
||||||
|
public static void setTextView (TextView theTextView)
|
||||||
|
{
|
||||||
|
if (myTextView != null)
|
||||||
|
{
|
||||||
|
myLog = myTextView.getText().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
myTextView = theTextView;
|
||||||
|
if (myTextView != null)
|
||||||
|
{
|
||||||
|
myTextView.setText (myLog);
|
||||||
|
myLog = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Interface implementation
|
||||||
|
public static void postMessage (String theText)
|
||||||
|
{
|
||||||
|
final String aCopy = new String (theText);
|
||||||
|
Log.e (myTag, theText);
|
||||||
|
|
||||||
|
myMutex.lock();
|
||||||
|
final TextView aView = myTextView;
|
||||||
|
if (aView == null)
|
||||||
|
{
|
||||||
|
myLog += aCopy;
|
||||||
|
myMutex.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aView.post (new Runnable()
|
||||||
|
{
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
aView.setText (aView.getText() + aCopy + "\n");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
myMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String myTag = "occtJniViewer";
|
||||||
|
private static final ReentrantLock myMutex = new ReentrantLock (true);
|
||||||
|
private static TextView myTextView = null;
|
||||||
|
private static String myLog = "";
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,218 @@
|
|||||||
|
// Copyright (c) 2014 OPEN CASCADE SAS
|
||||||
|
//
|
||||||
|
// This file is part of Open CASCADE Technology software library.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||||
|
// by the Free Software Foundation, with special exception defined in the file
|
||||||
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||||
|
// distribution for complete text of the license and disclaimer of any warranty.
|
||||||
|
//
|
||||||
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||||
|
// commercial license or contractual agreement.
|
||||||
|
|
||||||
|
package com.opencascade.jnisample;
|
||||||
|
|
||||||
|
import javax.microedition.khronos.egl.EGLConfig;
|
||||||
|
import javax.microedition.khronos.opengles.GL10;
|
||||||
|
|
||||||
|
import android.opengl.GLSurfaceView;
|
||||||
|
|
||||||
|
//! Wrapper for C++ OCCT viewer.
|
||||||
|
public class OcctJniRenderer implements GLSurfaceView.Renderer
|
||||||
|
{
|
||||||
|
|
||||||
|
//! Wrapper for V3d_TypeOfOrientation
|
||||||
|
enum TypeOfOrientation
|
||||||
|
{
|
||||||
|
Xpos, // front
|
||||||
|
Ypos, // left
|
||||||
|
Zpos, // top
|
||||||
|
Xneg, // back
|
||||||
|
Yneg, // right
|
||||||
|
Zneg // bottom
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Empty constructor.
|
||||||
|
OcctJniRenderer()
|
||||||
|
{
|
||||||
|
if (OcctJniActivity.areNativeLoaded)
|
||||||
|
{
|
||||||
|
myCppViewer = cppCreate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Open file.
|
||||||
|
public void open (String thePath)
|
||||||
|
{
|
||||||
|
if (myCppViewer != 0)
|
||||||
|
{
|
||||||
|
cppOpen (myCppViewer, thePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Update viewer.
|
||||||
|
public void onDrawFrame (GL10 theGl)
|
||||||
|
{
|
||||||
|
if (myCppViewer != 0)
|
||||||
|
{
|
||||||
|
cppRedraw (myCppViewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! (re)initialize viewer.
|
||||||
|
public void onSurfaceChanged (GL10 theGl, int theWidth, int theHeight)
|
||||||
|
{
|
||||||
|
if (myCppViewer != 0)
|
||||||
|
{
|
||||||
|
cppResize (myCppViewer, theWidth, theHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSurfaceCreated (GL10 theGl, EGLConfig theEglConfig)
|
||||||
|
{
|
||||||
|
if (myCppViewer != 0)
|
||||||
|
{
|
||||||
|
cppInit (myCppViewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Initialize rotation (remember first point position)
|
||||||
|
public void onStartRotation (int theStartX, int theStartY)
|
||||||
|
{
|
||||||
|
if (myCppViewer != 0)
|
||||||
|
{
|
||||||
|
cppStartRotation (myCppViewer, theStartX, theStartY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Perform rotation (relative to first point)
|
||||||
|
public void onRotation (int theX, int theY)
|
||||||
|
{
|
||||||
|
if (myCppViewer != 0)
|
||||||
|
{
|
||||||
|
cppOnRotation (myCppViewer, theX, theY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Perform panning
|
||||||
|
public void onPanning (int theDX, int theDY)
|
||||||
|
{
|
||||||
|
if (myCppViewer != 0)
|
||||||
|
{
|
||||||
|
cppOnPanning (myCppViewer, theDX, theDY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Perform selection
|
||||||
|
public void onClick (int theX, int theY)
|
||||||
|
{
|
||||||
|
if (myCppViewer != 0)
|
||||||
|
{
|
||||||
|
cppOnClick (myCppViewer, theX, theY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Stop previously active action (e.g. discard first rotation point)
|
||||||
|
public void onStopAction()
|
||||||
|
{
|
||||||
|
if (myCppViewer != 0)
|
||||||
|
{
|
||||||
|
cppStopAction (myCppViewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Fit All
|
||||||
|
public void fitAll()
|
||||||
|
{
|
||||||
|
if (myCppViewer != 0)
|
||||||
|
{
|
||||||
|
cppFitAll (myCppViewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Move camera
|
||||||
|
public void setProj (TypeOfOrientation theProj)
|
||||||
|
{
|
||||||
|
if (myCppViewer == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (theProj)
|
||||||
|
{
|
||||||
|
case Xpos: cppSetXposProj (myCppViewer); break;
|
||||||
|
case Ypos: cppSetYposProj (myCppViewer); break;
|
||||||
|
case Zpos: cppSetZposProj (myCppViewer); break;
|
||||||
|
case Xneg: cppSetXnegProj (myCppViewer); break;
|
||||||
|
case Yneg: cppSetYnegProj (myCppViewer); break;
|
||||||
|
case Zneg: cppSetZnegProj (myCppViewer); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Post message to the text view.
|
||||||
|
public void postMessage (String theText)
|
||||||
|
{
|
||||||
|
OcctJniLogger.postMessage (theText);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Create instance of C++ class
|
||||||
|
private native long cppCreate();
|
||||||
|
|
||||||
|
//! Destroy instance of C++ class
|
||||||
|
private native void cppDestroy (long theCppPtr);
|
||||||
|
|
||||||
|
//! Initialize OCCT viewer (steal OpenGL ES context bound to this thread)
|
||||||
|
private native void cppInit (long theCppPtr);
|
||||||
|
|
||||||
|
//! Resize OCCT viewer
|
||||||
|
private native void cppResize (long theCppPtr, int theWidth, int theHeight);
|
||||||
|
|
||||||
|
//! Open CAD file
|
||||||
|
private native void cppOpen (long theCppPtr, String thePath);
|
||||||
|
|
||||||
|
//! Handle detection in the viewer
|
||||||
|
private native void cppMoveTo (long theCppPtr, int theX, int theY);
|
||||||
|
|
||||||
|
//! Redraw OCCT viewer
|
||||||
|
private native void cppRedraw (long theCppPtr);
|
||||||
|
|
||||||
|
//! Fit All
|
||||||
|
private native void cppFitAll (long theCppPtr);
|
||||||
|
|
||||||
|
//! Move camera
|
||||||
|
private native void cppSetXposProj (long theCppPtr);
|
||||||
|
|
||||||
|
//! Move camera
|
||||||
|
private native void cppSetYposProj (long theCppPtr);
|
||||||
|
|
||||||
|
//! Move camera
|
||||||
|
private native void cppSetZposProj (long theCppPtr);
|
||||||
|
|
||||||
|
//! Move camera
|
||||||
|
private native void cppSetXnegProj (long theCppPtr);
|
||||||
|
|
||||||
|
//! Move camera
|
||||||
|
private native void cppSetYnegProj (long theCppPtr);
|
||||||
|
|
||||||
|
//! Move camera
|
||||||
|
private native void cppSetZnegProj (long theCppPtr);
|
||||||
|
|
||||||
|
//! Initialize rotation
|
||||||
|
private native void cppStartRotation (long theCppPtr, int theStartX, int theStartY);
|
||||||
|
|
||||||
|
//! Perform rotation
|
||||||
|
private native void cppOnRotation (long theCppPtr, int theX, int theY);
|
||||||
|
|
||||||
|
//! Perform panning
|
||||||
|
private native void cppOnPanning (long theCppPtr, int theDX, int theDY);
|
||||||
|
|
||||||
|
//! Perform selection
|
||||||
|
private native void cppOnClick (long theCppPtr, int theX, int theY);
|
||||||
|
|
||||||
|
//! Stop action (rotation / panning / scaling)
|
||||||
|
private native void cppStopAction (long theCppPtr);
|
||||||
|
|
||||||
|
private long myCppViewer = 0; //!< pointer to c++ class instance
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,332 @@
|
|||||||
|
// Copyright (c) 2014 OPEN CASCADE SAS
|
||||||
|
//
|
||||||
|
// This file is part of Open CASCADE Technology software library.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||||
|
// by the Free Software Foundation, with special exception defined in the file
|
||||||
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||||
|
// distribution for complete text of the license and disclaimer of any warranty.
|
||||||
|
//
|
||||||
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||||
|
// commercial license or contractual agreement.
|
||||||
|
|
||||||
|
package com.opencascade.jnisample;
|
||||||
|
|
||||||
|
import android.app.ActionBar.LayoutParams;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.PointF;
|
||||||
|
import android.opengl.GLSurfaceView;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import javax.microedition.khronos.egl.EGL10;
|
||||||
|
import javax.microedition.khronos.egl.EGLConfig;
|
||||||
|
import javax.microedition.khronos.egl.EGLContext;
|
||||||
|
import javax.microedition.khronos.egl.EGLDisplay;
|
||||||
|
|
||||||
|
//! OpenGL ES 2.0+ view.
|
||||||
|
//! Performs rendering in parallel thread.
|
||||||
|
class OcctJniView extends GLSurfaceView
|
||||||
|
{
|
||||||
|
|
||||||
|
// ! Default constructor.
|
||||||
|
public OcctJniView (Context theContext,
|
||||||
|
AttributeSet theAttrs)
|
||||||
|
{
|
||||||
|
super (theContext, theAttrs);
|
||||||
|
|
||||||
|
setPreserveEGLContextOnPause (true);
|
||||||
|
setEGLContextFactory (new ContextFactory());
|
||||||
|
setEGLConfigChooser (new ConfigChooser());
|
||||||
|
|
||||||
|
RelativeLayout.LayoutParams aLParams = new RelativeLayout.LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||||
|
aLParams.addRule (RelativeLayout.ALIGN_TOP);
|
||||||
|
|
||||||
|
myRenderer = new OcctJniRenderer();
|
||||||
|
setRenderer (myRenderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Open file.
|
||||||
|
public void open (String thePath)
|
||||||
|
{
|
||||||
|
final String aPath = thePath;
|
||||||
|
queueEvent (new Runnable() { public void run() { myRenderer.open (aPath); }});
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Create OpenGL ES 2.0+ context
|
||||||
|
private static class ContextFactory implements GLSurfaceView.EGLContextFactory
|
||||||
|
{
|
||||||
|
private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||||
|
public EGLContext createContext (EGL10 theEgl,
|
||||||
|
EGLDisplay theEglDisplay,
|
||||||
|
EGLConfig theEglConfig)
|
||||||
|
{
|
||||||
|
if (theEglConfig == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset EGL errors stack
|
||||||
|
int anError = EGL10.EGL_SUCCESS;
|
||||||
|
while ((anError = theEgl.eglGetError()) != EGL10.EGL_SUCCESS) {}
|
||||||
|
|
||||||
|
int[] anAttribs = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
|
||||||
|
EGLContext aEglContext = theEgl.eglCreateContext (theEglDisplay, theEglConfig, EGL10.EGL_NO_CONTEXT, anAttribs);
|
||||||
|
|
||||||
|
while ((anError = theEgl.eglGetError()) != EGL10.EGL_SUCCESS)
|
||||||
|
{
|
||||||
|
OcctJniLogger.postMessage ("Error: eglCreateContext() " + String.format ("0x%x", anError));
|
||||||
|
}
|
||||||
|
return aEglContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroyContext (EGL10 theEgl,
|
||||||
|
EGLDisplay theEglDisplay,
|
||||||
|
EGLContext theEglContext)
|
||||||
|
{
|
||||||
|
theEgl.eglDestroyContext (theEglDisplay, theEglContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Search for RGB24 config with depth and stencil buffers
|
||||||
|
private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser
|
||||||
|
{
|
||||||
|
//! Reset EGL errors stack
|
||||||
|
private void popEglErrors (EGL10 theEgl)
|
||||||
|
{
|
||||||
|
int anError = EGL10.EGL_SUCCESS;
|
||||||
|
while ((anError = theEgl.eglGetError()) != EGL10.EGL_SUCCESS)
|
||||||
|
{
|
||||||
|
OcctJniLogger.postMessage ("EGL Error: " + String.format ("0x%x", anError));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Auxiliary method to dump EGL configuration - for debugging purposes
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private void printConfig (EGL10 theEgl,
|
||||||
|
EGLDisplay theEglDisplay,
|
||||||
|
EGLConfig theEglConfig)
|
||||||
|
{
|
||||||
|
int[] THE_ATTRIBS =
|
||||||
|
{
|
||||||
|
EGL10.EGL_BUFFER_SIZE, EGL10.EGL_ALPHA_SIZE, EGL10.EGL_BLUE_SIZE, EGL10.EGL_GREEN_SIZE, EGL10.EGL_RED_SIZE, EGL10.EGL_DEPTH_SIZE, EGL10.EGL_STENCIL_SIZE,
|
||||||
|
EGL10.EGL_CONFIG_CAVEAT,
|
||||||
|
EGL10.EGL_CONFIG_ID,
|
||||||
|
EGL10.EGL_LEVEL,
|
||||||
|
EGL10.EGL_MAX_PBUFFER_HEIGHT, EGL10.EGL_MAX_PBUFFER_PIXELS, EGL10.EGL_MAX_PBUFFER_WIDTH,
|
||||||
|
EGL10.EGL_NATIVE_RENDERABLE, EGL10.EGL_NATIVE_VISUAL_ID, EGL10.EGL_NATIVE_VISUAL_TYPE,
|
||||||
|
0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
|
||||||
|
EGL10.EGL_SAMPLES, EGL10.EGL_SAMPLE_BUFFERS,
|
||||||
|
EGL10.EGL_SURFACE_TYPE,
|
||||||
|
EGL10.EGL_TRANSPARENT_TYPE, EGL10.EGL_TRANSPARENT_RED_VALUE, EGL10.EGL_TRANSPARENT_GREEN_VALUE, EGL10.EGL_TRANSPARENT_BLUE_VALUE,
|
||||||
|
0x3039, 0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGB, EGL10.EGL_BIND_TO_TEXTURE_RGBA,
|
||||||
|
0x303B, 0x303C, // EGL10.EGL_MIN_SWAP_INTERVAL, EGL10.EGL_MAX_SWAP_INTERVAL
|
||||||
|
EGL10.EGL_LUMINANCE_SIZE, EGL10.EGL_ALPHA_MASK_SIZE,
|
||||||
|
EGL10.EGL_COLOR_BUFFER_TYPE, EGL10.EGL_RENDERABLE_TYPE,
|
||||||
|
0x3042 // EGL10.EGL_CONFORMANT
|
||||||
|
};
|
||||||
|
String[] THE_NAMES =
|
||||||
|
{
|
||||||
|
"EGL_BUFFER_SIZE", "EGL_ALPHA_SIZE", "EGL_BLUE_SIZE", "EGL_GREEN_SIZE", "EGL_RED_SIZE", "EGL_DEPTH_SIZE", "EGL_STENCIL_SIZE",
|
||||||
|
"EGL_CONFIG_CAVEAT",
|
||||||
|
"EGL_CONFIG_ID",
|
||||||
|
"EGL_LEVEL",
|
||||||
|
"EGL_MAX_PBUFFER_HEIGHT", "EGL_MAX_PBUFFER_PIXELS", "EGL_MAX_PBUFFER_WIDTH",
|
||||||
|
"EGL_NATIVE_RENDERABLE", "EGL_NATIVE_VISUAL_ID", "EGL_NATIVE_VISUAL_TYPE",
|
||||||
|
"EGL_PRESERVED_RESOURCES",
|
||||||
|
"EGL_SAMPLES", "EGL_SAMPLE_BUFFERS",
|
||||||
|
"EGL_SURFACE_TYPE",
|
||||||
|
"EGL_TRANSPARENT_TYPE", "EGL_TRANSPARENT_RED_VALUE", "EGL_TRANSPARENT_GREEN_VALUE", "EGL_TRANSPARENT_BLUE_VALUE",
|
||||||
|
"EGL_BIND_TO_TEXTURE_RGB", "EGL_BIND_TO_TEXTURE_RGBA",
|
||||||
|
"EGL_MIN_SWAP_INTERVAL", "EGL_MAX_SWAP_INTERVAL",
|
||||||
|
"EGL_LUMINANCE_SIZE", "EGL_ALPHA_MASK_SIZE",
|
||||||
|
"EGL_COLOR_BUFFER_TYPE", "EGL_RENDERABLE_TYPE",
|
||||||
|
"EGL_CONFORMANT"
|
||||||
|
};
|
||||||
|
int[] aValue = new int[1];
|
||||||
|
for (int anAttrIter = 0; anAttrIter < THE_ATTRIBS.length; ++anAttrIter)
|
||||||
|
{
|
||||||
|
int anAttr = THE_ATTRIBS[anAttrIter];
|
||||||
|
String aName = THE_NAMES [anAttrIter];
|
||||||
|
if (theEgl.eglGetConfigAttrib (theEglDisplay, theEglConfig, anAttr, aValue))
|
||||||
|
{
|
||||||
|
OcctJniLogger.postMessage (String.format (" %s: %d\n", aName, aValue[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
popEglErrors (theEgl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Interface implementation
|
||||||
|
public EGLConfig chooseConfig (EGL10 theEgl,
|
||||||
|
EGLDisplay theEglDisplay)
|
||||||
|
{
|
||||||
|
int EGL_OPENGL_ES2_BIT = 4;
|
||||||
|
int[] aCfgAttribs =
|
||||||
|
{
|
||||||
|
EGL10.EGL_RED_SIZE, 8,
|
||||||
|
EGL10.EGL_GREEN_SIZE, 8,
|
||||||
|
EGL10.EGL_BLUE_SIZE, 8,
|
||||||
|
EGL10.EGL_ALPHA_SIZE, 0,
|
||||||
|
EGL10.EGL_DEPTH_SIZE, 24,
|
||||||
|
EGL10.EGL_STENCIL_SIZE, 8,
|
||||||
|
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||||
|
EGL10.EGL_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
EGLConfig aConfigs[] = new EGLConfig[1];
|
||||||
|
int[] aNbConfigs = new int[1];
|
||||||
|
if (!theEgl.eglChooseConfig (theEglDisplay, aCfgAttribs, aConfigs, 1, aNbConfigs)
|
||||||
|
|| aConfigs[0] == null)
|
||||||
|
{
|
||||||
|
aCfgAttribs[4 * 2 + 1] = 16; // try config with smaller depth buffer
|
||||||
|
popEglErrors (theEgl);
|
||||||
|
if (!theEgl.eglChooseConfig (theEglDisplay, aCfgAttribs, aConfigs, 1, aNbConfigs)
|
||||||
|
|| aConfigs[0] == null)
|
||||||
|
{
|
||||||
|
OcctJniLogger.postMessage ("Error: eglChooseConfig() has failed!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//printConfig (theEgl, theEglDisplay, aConfigs[0]);
|
||||||
|
return aConfigs[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Callback to handle touch events
|
||||||
|
@Override public boolean onTouchEvent (MotionEvent theEvent)
|
||||||
|
{
|
||||||
|
int aPointerIndex = theEvent.getActionIndex();
|
||||||
|
int aPointerId = theEvent.getPointerId (aPointerIndex);
|
||||||
|
int aMaskedAction = theEvent.getActionMasked();
|
||||||
|
switch (aMaskedAction)
|
||||||
|
{
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
case MotionEvent.ACTION_POINTER_DOWN:
|
||||||
|
{
|
||||||
|
PointF aPntLast = null;
|
||||||
|
if (myActivePointers.size() >= 1)
|
||||||
|
{
|
||||||
|
aPntLast = myActivePointers.get (myActivePointers.keyAt (0));
|
||||||
|
}
|
||||||
|
|
||||||
|
final PointF aPnt = new PointF();
|
||||||
|
aPnt.x = theEvent.getX (aPointerIndex);
|
||||||
|
aPnt.y = theEvent.getY (aPointerIndex);
|
||||||
|
myActivePointers.put (aPointerId, aPnt);
|
||||||
|
|
||||||
|
switch (myActivePointers.size())
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
final int aStartX = (int )aPnt.x;
|
||||||
|
final int aStartY = (int )aPnt.y;
|
||||||
|
queueEvent (new Runnable() { public void run() { myRenderer.onStartRotation (aStartX, aStartY); }});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
myPanFrom.x = (aPntLast.x + aPnt.x) * 0.5f;
|
||||||
|
myPanFrom.y = (aPntLast.y + aPnt.y) * 0.5f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
{
|
||||||
|
for (int aNbPointers = theEvent.getPointerCount(), aPntIter = 0; aPntIter < aNbPointers; ++aPntIter)
|
||||||
|
{
|
||||||
|
PointF aPnt = myActivePointers.get (theEvent.getPointerId (aPntIter));
|
||||||
|
if (aPnt != null)
|
||||||
|
{
|
||||||
|
aPnt.x = theEvent.getX (aPntIter);
|
||||||
|
aPnt.y = theEvent.getY (aPntIter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (myActivePointers.size())
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
PointF aPnt = myActivePointers.get (theEvent.getPointerId (0));
|
||||||
|
final int anX = (int )aPnt.x;
|
||||||
|
final int anY = (int )aPnt.y;
|
||||||
|
queueEvent (new Runnable() { public void run() { myRenderer.onRotation (anX, anY); }});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
PointF aPnt1 = myActivePointers.get (myActivePointers.keyAt (0));
|
||||||
|
PointF aPnt2 = myActivePointers.get (myActivePointers.keyAt (1));
|
||||||
|
PointF aPntAver = new PointF ((aPnt1.x + aPnt2.x) * 0.5f,
|
||||||
|
(aPnt1.y + aPnt2.y) * 0.5f);
|
||||||
|
final int aDX = (int )(aPntAver.x - myPanFrom.x);
|
||||||
|
final int aDY = (int )(myPanFrom.y -aPntAver.y);
|
||||||
|
myPanFrom.x = aPntAver.x;
|
||||||
|
myPanFrom.y = aPntAver.y;
|
||||||
|
queueEvent (new Runnable() { public void run() { myRenderer.onPanning (aDX, aDY); }});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
case MotionEvent.ACTION_POINTER_UP:
|
||||||
|
case MotionEvent.ACTION_CANCEL:
|
||||||
|
{
|
||||||
|
myActivePointers.remove (aPointerId);
|
||||||
|
if (myActivePointers.size() == 0)
|
||||||
|
{
|
||||||
|
final int aPressX = (int )theEvent.getX (aPointerIndex);
|
||||||
|
final int aPressY = (int )theEvent.getY (aPointerIndex);
|
||||||
|
double aPressTimeMs = theEvent.getEventTime() - theEvent.getDownTime();
|
||||||
|
if (aPressTimeMs < 100.0)
|
||||||
|
{
|
||||||
|
queueEvent (new Runnable() { public void run() { myRenderer.onClick (aPressX, aPressY); }});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (myActivePointers.size() == 1)
|
||||||
|
{
|
||||||
|
PointF aPnt = myActivePointers.get (myActivePointers.keyAt (0));
|
||||||
|
final int aStartX = (int )aPnt.x;
|
||||||
|
final int aStartY = (int )aPnt.y;
|
||||||
|
queueEvent (new Runnable() { public void run() { myRenderer.onStartRotation (aStartX, aStartY); }});
|
||||||
|
}
|
||||||
|
//queueEvent (new Runnable() { public void run() { myRenderer.onStopAction(); }});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///invalidate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Fit All
|
||||||
|
public void fitAll()
|
||||||
|
{
|
||||||
|
queueEvent (new Runnable() { public void run() { myRenderer.fitAll(); }});
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Move camera
|
||||||
|
public void setProj (final OcctJniRenderer.TypeOfOrientation theProj)
|
||||||
|
{
|
||||||
|
queueEvent (new Runnable() { public void run() { myRenderer.setProj (theProj); }});
|
||||||
|
}
|
||||||
|
|
||||||
|
//! OCCT viewer
|
||||||
|
private OcctJniRenderer myRenderer = null;
|
||||||
|
|
||||||
|
//! Touch events cache
|
||||||
|
private SparseArray<PointF> myActivePointers = new SparseArray<PointF>();
|
||||||
|
|
||||||
|
//! Starting point for panning event
|
||||||
|
private PointF myPanFrom = new PointF (0.0f, 0.0f);
|
||||||
|
|
||||||
|
}
|