Compare commits

..

No commits in common. "master" and "1.0.0" have entirely different histories.

14 changed files with 212 additions and 278 deletions

3
.github/FUNDING.yml vendored
View File

@ -1,3 +0,0 @@
github: defold
patreon: Defold
custom: ['https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=NBNBHTUW4GS4C']

View File

@ -1,19 +0,0 @@
name: Trigger site rebuild
on: [push]
jobs:
site-rebuild:
runs-on: ubuntu-latest
steps: [
{
name: 'Repository dispatch',
uses: defold/repository-dispatch@1.2.1,
with: {
repo: 'defold/defold.github.io',
token: '${{ secrets.SERVICES_GITHUB_TOKEN }}',
user: 'services@defold.se',
action: 'extension-camera'
}
}]

102
README.md
View File

@ -1,5 +1,101 @@
# Camera extension for Defold # extension-camera
Defold [native extension](https://www.defold.com/manuals/extensions/) which provides access to the camera on macOS, iOS and Android. Native extension to use device camera to capture frames.
[Manual, API and setup instructions](https://www.defold.com/extension-camera/) is available on the official Defold site.
# Installation
To use the camera extension in a Defold project this project has to be added as a [Defold library dependency](http://www.defold.com/manuals/libraries/). Open the **game.project** file and in the [Dependencies field in the Project section](https://defold.com/manuals/project-settings/#dependencies) add:
https://github.com/defold/extension-camera/archive/master.zip
Or point to the ZIP file of [a specific release](https://github.com/defold/extension-camera/releases).
# Supported platforms
The currently supported platforms are macOS, iOS and Android
# FAQ
## How do I reset macOS camera permission?
To test macOS camera permission popup multiple times you can reset the permission from the terminal:
```bash
tccutil reset Camera
```
# Lua API
## Type constants
Describes what camera should be used.
```lua
camera.CAMERA_TYPE_FRONT -- Selfie
camera.CAMERA_TYPE_BACK
```
## Quality constants
```lua
camera.CAPTURE_QUALITY_HIGH
camera.CAPTURE_QUALITY_MEDIUM
camera.CAPTURE_QUALITY_LOW
```
## Status constants
```lua
camera.CAMERA_STARTED
camera.CAMERA_STOPPED
camera.CAMERA_NOT_PERMITTED
camera.CAMERA_ERROR
```
## camera.start_capture(type, quality, callback)
Start camera capture using the specified camera (front/back) and capture quality. This may trigger a camera usage permission popup. When the popup has been dismissed the callback will be invoked with camera start status.
```lua
camera.start_capture(camera.CAMERA_TYPE_BACK, camera.CAPTURE_QUALITY_HIGH, function(self, message)
if message == camera.CAMERA_STARTED then
-- do stuff
end
end)
```
## camera.stop_capture()
Stops a previously started capture session.
```lua
camera.stop_capture()
```
## camera.get_info()
Gets the info from the current capture session.
```lua
local info = camera.get_info()
print("width", info.width)
print("height", info.height)
```
## camera.get_frame()
Retrieves the camera pixel buffer. This buffer has one stream named "rgb", and is of type `buffer.VALUE_TYPE_UINT8` and has the value count of 1.
```lua
self.cameraframe = camera.get_frame()
```

View File

@ -1,121 +0,0 @@
- name: camera
type: table
desc: Provides functionality to capture images using the camera. Supported on macOS, iOS and Android.
[icon:ios] [icon:android]
members:
#*****************************************************************************************************
- name: start_capture
type: function
desc: Start camera capture using the specified camera (front/back) and capture quality. This may trigger a camera usage permission popup. When the popup has been dismissed the callback will be invoked with camera start status.
members:
- name: type
type: string
desc: Which camera to use, font or back.
- name: quality
type: string
desc: Quality of the captured image.
- name: callback
type: function
desc: |-
The function to call camera state has changed.
examples:
- desc: |-
```lua
camera.start_capture(camera.CAMERA_TYPE_BACK, camera.CAPTURE_QUALITY_HIGH, function(self, message)
if message == camera.CAMERA_STARTED then
-- do stuff
end
end)
```
#*****************************************************************************************************
- name: stop_capture
type: function
desc: Stops a previously started capture session.
examples:
- desc: |-
```lua
camera.stop_capture()
```
#*****************************************************************************************************
- name: get_info
type: function
desc: Gets the info from the current capture session.
return:
- name: info
type: table
desc: Information about the camera.
examples:
- desc: |-
```lua
local info = camera.get_info()
print("width", info.width)
print("height", info.height)
```
#*****************************************************************************************************
- name: get_frame
type: function
desc: Get captured frame.
return:
- name: frame
type: buffer
desc: Retrieves the camera pixel buffer. This buffer has one stream named "rgb", and is of type `buffer.VALUE_TYPE_UINT8` and has the value count of 1.
examples:
- desc: |-
```lua
self.cameraframe = camera.get_frame()
```
#*****************************************************************************************************
- name: CAMERA_TYPE_FRONT
type: string
desc: Constant for the front camera.
- name: CAMERA_TYPE_BACK
type: string
desc: Constant for the back camera.
#*****************************************************************************************************
- name: CAPTURE_QUALITY_HIGH
type: string
desc: High quality capture session.
- name: CAPTURE_QUALITY_MEDIUM
type: string
desc: Medium quality capture session.
- name: CAPTURE_QUALITY_LOW
type: string
desc: Low quality capture session.
#*****************************************************************************************************
- name: CAMERA_STARTED
type: string
desc: The capture session has started.
- name: CAMERA_STOPPED
type: string
desc: The capture session has stopped.
- name: CAMERA_NOT_PERMITTED
type: string
desc: The user did not give permission to start the capture session.
- name: CAMERA_ERROR
type: string
desc: Something went wrong when starting the capture session.

View File

@ -1,10 +1,18 @@
name: "Camera" name: "Camera"
platforms: platforms:
osx: x86_64-osx:
context:
frameworks: ["AVFoundation", "CoreMedia"]
x86-osx:
context: context:
frameworks: ["AVFoundation", "CoreMedia"] frameworks: ["AVFoundation", "CoreMedia"]
ios: arm64-ios:
context:
frameworks: ["AVFoundation", "CoreMedia", "UIKit"]
armv7-ios:
context: context:
frameworks: ["AVFoundation", "CoreMedia", "UIKit"] frameworks: ["AVFoundation", "CoreMedia", "UIKit"]

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="{{android.package}}"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" /> <uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />

View File

@ -1,7 +1,3 @@
repositories {
mavenCentral()
}
dependencies { dependencies {
implementation 'androidx.core:core:1.2.0' compile 'com.android.support:support-v4:28.+'
} }

View File

@ -7,7 +7,7 @@ import android.app.FragmentManager;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.Manifest; import android.Manifest;
import androidx.core.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.util.Log; import android.util.Log;
@ -45,7 +45,7 @@ public class AndroidCamera extends Fragment
private boolean newFrame; private boolean newFrame;
private int position; private int position;
private int quality; private int quality;
private Camera.Size previewSize; private Camera.Size size;
private static Context context; private static Context context;
@ -132,43 +132,26 @@ public class AndroidCamera extends Fragment
Camera.Parameters params = camera.getParameters(); Camera.Parameters params = camera.getParameters();
List<Camera.Size> previewSizes = params.getSupportedPreviewSizes(); List<Camera.Size> sizes = params.getSupportedPreviewSizes();
List<String> focusModes = params.getSupportedFocusModes();
List<Camera.Size> pictureSizes = params.getSupportedPictureSizes();
List<Integer> supportedFormats = params.getSupportedPictureFormats();
Camera.Size pictureSize;
switch(this.quality) switch(this.quality)
{ {
case CAPTURE_QUALITY_HIGH: case CAPTURE_QUALITY_HIGH:
this.previewSize = previewSizes.get(previewSizes.size() - 1); this.size = sizes.get(sizes.size() - 1);
pictureSize = pictureSizes.get(previewSizes.size() - 1);
break; break;
case CAPTURE_QUALITY_LOW: case CAPTURE_QUALITY_LOW:
this.previewSize = previewSizes.get(0); this.size = sizes.get(0);
pictureSize = pictureSizes.get(0);
break; break;
case CAPTURE_QUALITY_MEDIUM: case CAPTURE_QUALITY_MEDIUM:
default: default:
this.previewSize = previewSizes.get((int)Math.ceil(previewSizes.size() / 2)); this.size = sizes.get((int)Math.ceil(sizes.size() / 2));
pictureSize = pictureSizes.get((int)Math.ceil(previewSizes.size() / 2));
break; break;
} }
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) params.setPreviewSize(this.size.width, this.size.height);
{ params.setPictureSize(this.size.width, this.size.height);
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); params.setPictureFormat(PixelFormat.JPEG);
} params.setJpegQuality(90);
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
params.setPreviewSize(this.previewSize.width, this.previewSize.height);
params.setPictureSize(pictureSize.width, pictureSize.height);
if (supportedFormats.contains(PixelFormat.JPEG))
{
params.setPictureFormat(PixelFormat.JPEG);
params.setJpegQuality(90);
}
camera.setParameters(params); camera.setParameters(params);
final Activity activity = (Activity)context; final Activity activity = (Activity)context;
@ -183,7 +166,7 @@ public class AndroidCamera extends Fragment
if(rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270) if(rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270)
flip = true; flip = true;
int[] pixels = convertYUV420_NV21toARGB8888(data, AndroidCamera.this.previewSize.width, AndroidCamera.this.previewSize.height, flip); int[] pixels = convertYUV420_NV21toARGB8888(data, AndroidCamera.this.size.width, AndroidCamera.this.size.height, flip);
frameUpdate(pixels); frameUpdate(pixels);
} }
}); });
@ -196,7 +179,7 @@ public class AndroidCamera extends Fragment
{ {
} }
captureStarted(this.previewSize.width, this.previewSize.height); captureStarted(this.size.width, this.size.height);
camera.startPreview(); camera.startPreview();
queueMessage(CAMERA_STARTED); queueMessage(CAMERA_STARTED);
} }

View File

@ -7,6 +7,7 @@
#define MODULE_NAME "camera" #define MODULE_NAME "camera"
// Defold SDK // Defold SDK
#define DLIB_LOG_DOMAIN LIB_NAME
#include <dmsdk/sdk.h> #include <dmsdk/sdk.h>
#if defined(DM_PLATFORM_IOS) || defined(DM_PLATFORM_OSX) || defined(DM_PLATFORM_ANDROID) #if defined(DM_PLATFORM_IOS) || defined(DM_PLATFORM_OSX) || defined(DM_PLATFORM_ANDROID)
@ -47,30 +48,21 @@ void Camera_QueueMessage(CameraMessage message)
static void Camera_ProcessQueue() static void Camera_ProcessQueue()
{ {
if (g_DefoldCamera.m_MessageQueue.Empty()) DM_MUTEX_SCOPED_LOCK(g_DefoldCamera.m_Mutex);
{
return;
}
dmArray<CameraMessage> tmp; for (uint32_t i = 0; i != g_DefoldCamera.m_MessageQueue.Size(); ++i)
{
DM_MUTEX_SCOPED_LOCK(g_DefoldCamera.m_Mutex);
tmp.Swap(g_DefoldCamera.m_MessageQueue);
}
for (uint32_t i = 0; i != tmp.Size(); ++i)
{ {
lua_State* L = dmScript::GetCallbackLuaContext(g_DefoldCamera.m_Callback); lua_State* L = dmScript::GetCallbackLuaContext(g_DefoldCamera.m_Callback);
if (!dmScript::SetupCallback(g_DefoldCamera.m_Callback)) if (!dmScript::SetupCallback(g_DefoldCamera.m_Callback))
{ {
break; break;
} }
CameraMessage message = tmp[i]; CameraMessage message = g_DefoldCamera.m_MessageQueue[i];
if (message == CAMERA_STARTED) if (message == CAMERA_STARTED)
{ {
// Increase ref count // Increase ref count
dmScript::LuaHBuffer luabuffer(g_DefoldCamera.m_VideoBuffer, dmScript::OWNER_C); dmScript::LuaHBuffer luabuffer = {g_DefoldCamera.m_VideoBuffer, false};
dmScript::PushBuffer(L, luabuffer); dmScript::PushBuffer(L, luabuffer);
g_DefoldCamera.m_VideoBufferLuaRef = dmScript::Ref(L, LUA_REGISTRYINDEX); g_DefoldCamera.m_VideoBufferLuaRef = dmScript::Ref(L, LUA_REGISTRYINDEX);
} }
@ -88,6 +80,7 @@ static void Camera_ProcessQueue()
} }
dmScript::TeardownCallback(g_DefoldCamera.m_Callback); dmScript::TeardownCallback(g_DefoldCamera.m_Callback);
} }
g_DefoldCamera.m_MessageQueue.SetSize(0);
} }
static void Camera_DestroyCallback() static void Camera_DestroyCallback()

View File

@ -3,7 +3,6 @@
#if defined(DM_PLATFORM_ANDROID) #if defined(DM_PLATFORM_ANDROID)
#include "camera_private.h" #include "camera_private.h"
#include <dmsdk/dlib/android.h>
static jclass g_CameraClass = 0; static jclass g_CameraClass = 0;
static jobject g_CameraObject = 0; static jobject g_CameraObject = 0;
@ -21,20 +20,53 @@ static CaptureQuality g_Quality;
static dmBuffer::HBuffer* g_Buffer = 0; static dmBuffer::HBuffer* g_Buffer = 0;
static JNIEnv* Attach()
{
JNIEnv* env;
JavaVM* vm = dmGraphics::GetNativeAndroidJavaVM();
vm->AttachCurrentThread(&env, NULL);
return env;
}
static bool Detach(JNIEnv* env)
{
bool exception = (bool) env->ExceptionCheck();
env->ExceptionClear();
JavaVM* vm = dmGraphics::GetNativeAndroidJavaVM();
vm->DetachCurrentThread();
return !exception;
}
static jclass GetClass(JNIEnv* env, const char* classname)
{
jclass activity_class = env->FindClass("android/app/NativeActivity");
jmethodID get_class_loader = env->GetMethodID(activity_class,"getClassLoader", "()Ljava/lang/ClassLoader;");
jobject cls = env->CallObjectMethod(dmGraphics::GetNativeAndroidActivity(), get_class_loader);
jclass class_loader = env->FindClass("java/lang/ClassLoader");
jmethodID find_class = env->GetMethodID(class_loader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
jstring str_class_name = env->NewStringUTF(classname);
jclass outcls = (jclass)env->CallObjectMethod(cls, find_class, str_class_name);
env->DeleteLocalRef(str_class_name);
return outcls;
}
extern "C" extern "C"
{ {
JNIEXPORT void JNICALL Java_com_defold_android_camera_AndroidCamera_frameUpdate(JNIEnv * env, jobject jobj, jintArray data); JNIEXPORT void JNICALL Java_com_defold_android_camera_AndroidCamera_frameUpdate(JNIEnv * env, jobject jobj, jintArray data);
JNIEXPORT void JNICALL Java_com_defold_android_camera_AndroidCamera_queueMessage(JNIEnv * env, jobject jobj, jint message); JNIEXPORT void JNICALL Java_com_defold_android_camera_AndroidCamera_queueMessage(JNIEnv * env, jobject jobj, jint message);
JNIEXPORT void JNICALL Java_com_defold_android_camera_AndroidCamera_captureStarted(JNIEnv * env, jobject jobj, jint width, jint height); JNIEXPORT void JNICALL Java_com_defold_android_camera_AndroidCamera_captureStarted(JNIEnv * env, jobject jobj, jint width, jint height);
} }
JNIEXPORT void JNICALL Java_com_defold_android_camera_AndroidCamera_frameUpdate(JNIEnv * env, jobject jobj, jintArray data) JNIEXPORT void JNICALL Java_com_defold_android_camera_AndroidCamera_frameUpdate(JNIEnv * env, jobject jobj, jintArray data)
{ {
if(!g_FrameLock) if(!g_FrameLock)
{ {
env->GetIntArrayRegion(data, 0, g_Width * g_Height, g_Data); env->GetIntArrayRegion(data, 0, g_Width * g_Height, g_Data);
g_FrameLock = true; g_FrameLock = true;
} }
} }
JNIEXPORT void JNICALL Java_com_defold_android_camera_AndroidCamera_queueMessage(JNIEnv * env, jobject jobj, jint message) JNIEXPORT void JNICALL Java_com_defold_android_camera_AndroidCamera_queueMessage(JNIEnv * env, jobject jobj, jint message)
@ -66,15 +98,19 @@ void CameraPlatform_GetCameraInfo(CameraInfo& outparams)
int CameraPlatform_Initialize() int CameraPlatform_Initialize()
{ {
dmAndroid::ThreadAttacher threadAttacher; JNIEnv* env = Attach();
JNIEnv* env = threadAttacher.GetEnv(); if(!env)
{
return false;
}
// get the AndroidCamera class // get the AndroidCamera class
jclass tmp = dmAndroid::LoadClass(env, "com.defold.android.camera/AndroidCamera"); jclass tmp = GetClass(env, "com.defold.android.camera/AndroidCamera");
g_CameraClass = (jclass)env->NewGlobalRef(tmp); g_CameraClass = (jclass)env->NewGlobalRef(tmp);
if(!g_CameraClass) if(!g_CameraClass)
{ {
dmLogError("Could not find class 'com.defold.android.camera/AndroidCamera'."); dmLogError("Could not find class 'com.defold.android.camera/AndroidCamera'.");
Detach(env);
return false; return false;
} }
@ -83,6 +119,7 @@ int CameraPlatform_Initialize()
if(!g_GetCameraMethodId) if(!g_GetCameraMethodId)
{ {
dmLogError("Could not get static method 'getCamera'."); dmLogError("Could not get static method 'getCamera'.");
Detach(env);
return false; return false;
} }
@ -91,6 +128,7 @@ int CameraPlatform_Initialize()
if(!g_CameraObject) if(!g_CameraObject)
{ {
dmLogError("Could not create instance."); dmLogError("Could not create instance.");
Detach(env);
return false; return false;
} }
@ -99,15 +137,18 @@ int CameraPlatform_Initialize()
if(!g_StartPreviewMethodId) if(!g_StartPreviewMethodId)
{ {
dmLogError("Could not get startPreview() method."); dmLogError("Could not get startPreview() method.");
Detach(env);
return false; return false;
} }
g_StopPreviewMethodId = env->GetMethodID(g_CameraClass, "stopPreview", "()V"); g_StopPreviewMethodId = env->GetMethodID(g_CameraClass, "stopPreview", "()V");
if(!g_StopPreviewMethodId) if(!g_StopPreviewMethodId)
{ {
dmLogError("Could not get stopPreview() method."); dmLogError("Could not get stopPreview() method.");
Detach(env);
return false; return false;
} }
Detach(env);
return true; return true;
} }
@ -123,9 +164,9 @@ void CameraPlatform_StartCapture(dmBuffer::HBuffer* buffer, CameraType type, Cap
g_Type = type; g_Type = type;
g_Quality = quality; g_Quality = quality;
dmAndroid::ThreadAttacher threadAttacher; JNIEnv* env = Attach();
JNIEnv* env = threadAttacher.GetEnv(); env->CallVoidMethod(g_CameraObject, g_StartPreviewMethodId);
env->CallVoidMethod(g_CameraObject, g_StartPreviewMethodId); Detach(env);
} }
void CameraPlatform_StopCapture() void CameraPlatform_StopCapture()
@ -136,15 +177,15 @@ void CameraPlatform_StopCapture()
return; return;
} }
dmAndroid::ThreadAttacher threadAttacher; JNIEnv* env = Attach();
JNIEnv* env = threadAttacher.GetEnv();
env->CallVoidMethod(g_CameraObject, g_StopPreviewMethodId); env->CallVoidMethod(g_CameraObject, g_StopPreviewMethodId);
Detach(env);
} }
void CameraPlatform_UpdateCapture() void CameraPlatform_UpdateCapture()
{ {
if(g_FrameLock) if(g_FrameLock)
{ {
int width = g_Width; int width = g_Width;
int height = g_Height; int height = g_Height;
int numChannels = 4; int numChannels = 4;
@ -168,8 +209,8 @@ void CameraPlatform_UpdateCapture()
out[index+2] = (argb>>16)&0xFF; // B out[index+2] = (argb>>16)&0xFF; // B
} }
} }
g_FrameLock = false; g_FrameLock = false;
} }
} }
#endif // DM_PLATFORM_ANDROID #endif // DM_PLATFORM_ANDROID

View File

@ -1,37 +0,0 @@
---
title: Defold camera extension API documentation
brief: This manual covers how to use the camera on macOS, iOS and Android in Defold.
---
# Defold camera extension API documentation
This extension provides a unified, simple to use interface to capture images using the camera on macOS, iOS and Android.
## Installation
To use this library in your Defold project, add the following URL to your `game.project` dependencies:
https://github.com/defold/extension-camera/archive/master.zip
We recommend using a link to a zip file of a [specific release](https://github.com/defold/extension-camera/releases).
## Example
Refer to the [example project](https://github.com/defold/extension-camera/blob/master/main/main.script).
## FAQ
### How do I reset macOS camera permission?
To test macOS camera permission popup multiple times you can reset the permission from the terminal:
```bash
tccutil reset Camera
```
## Source code
The source code is available on [GitHub](https://github.com/defold/extension-camera)

View File

@ -1,8 +0,0 @@
font: "/builtins/fonts/vera_mo_bd.ttf"
material: "/builtins/fonts/font-df.material"
size: 14
antialias: 1
alpha: 1.0
shadow_alpha: 0.0
shadow_blur: 0
output_format: TYPE_DISTANCE_FIELD

View File

@ -16,19 +16,14 @@ embedded_instances {
" z: 0.0\n" " z: 0.0\n"
" w: 1.0\n" " w: 1.0\n"
" }\n" " }\n"
" property_decls {\n"
" }\n"
"}\n" "}\n"
"embedded_components {\n" "embedded_components {\n"
" id: \"sprite\"\n" " id: \"sprite\"\n"
" type: \"sprite\"\n" " type: \"sprite\"\n"
" data: \"default_animation: \\\"logo\\\"\\n" " data: \"tile_set: \\\"/main/camera.atlas\\\"\\n"
"default_animation: \\\"logo\\\"\\n"
"material: \\\"/builtins/materials/sprite.material\\\"\\n" "material: \\\"/builtins/materials/sprite.material\\\"\\n"
"blend_mode: BLEND_MODE_ALPHA\\n" "blend_mode: BLEND_MODE_ALPHA\\n"
"textures {\\n"
" sampler: \\\"texture_sampler\\\"\\n"
" texture: \\\"/main/camera.atlas\\\"\\n"
"}\\n"
"\"\n" "\"\n"
" position {\n" " position {\n"
" x: 0.0\n" " x: 0.0\n"
@ -65,13 +60,10 @@ embedded_instances {
data: "embedded_components {\n" data: "embedded_components {\n"
" id: \"sprite\"\n" " id: \"sprite\"\n"
" type: \"sprite\"\n" " type: \"sprite\"\n"
" data: \"default_animation: \\\"logo\\\"\\n" " data: \"tile_set: \\\"/main/logo.atlas\\\"\\n"
"default_animation: \\\"logo\\\"\\n"
"material: \\\"/builtins/materials/sprite.material\\\"\\n" "material: \\\"/builtins/materials/sprite.material\\\"\\n"
"blend_mode: BLEND_MODE_ALPHA\\n" "blend_mode: BLEND_MODE_ALPHA\\n"
"textures {\\n"
" sampler: \\\"texture_sampler\\\"\\n"
" texture: \\\"/main/logo.atlas\\\"\\n"
"}\\n"
"\"\n" "\"\n"
" position {\n" " position {\n"
" x: 0.0\n" " x: 0.0\n"
@ -94,6 +86,12 @@ embedded_instances {
" z: 0.0\\n" " z: 0.0\\n"
" w: 0.0\\n" " w: 0.0\\n"
"}\\n" "}\\n"
"scale {\\n"
" x: 1.0\\n"
" y: 1.0\\n"
" z: 1.0\\n"
" w: 0.0\\n"
"}\\n"
"color {\\n" "color {\\n"
" x: 1.0\\n" " x: 1.0\\n"
" y: 1.0\\n" " y: 1.0\\n"
@ -118,8 +116,8 @@ embedded_instances {
"blend_mode: BLEND_MODE_ALPHA\\n" "blend_mode: BLEND_MODE_ALPHA\\n"
"line_break: false\\n" "line_break: false\\n"
"text: \\\"Space/Touch to toggle capture\\\"\\n" "text: \\\"Space/Touch to toggle capture\\\"\\n"
"font: \\\"/main/default.font\\\"\\n" "font: \\\"/builtins/fonts/system_font.font\\\"\\n"
"material: \\\"/builtins/fonts/label-df.material\\\"\\n" "material: \\\"/builtins/fonts/label.material\\\"\\n"
"\"\n" "\"\n"
" position {\n" " position {\n"
" x: 90.0\n" " x: 90.0\n"
@ -142,6 +140,12 @@ embedded_instances {
" z: 0.0\\n" " z: 0.0\\n"
" w: 0.0\\n" " w: 0.0\\n"
"}\\n" "}\\n"
"scale {\\n"
" x: 1.0\\n"
" y: 1.0\\n"
" z: 1.0\\n"
" w: 0.0\\n"
"}\\n"
"color {\\n" "color {\\n"
" x: 1.0\\n" " x: 1.0\\n"
" y: 1.0\\n" " y: 1.0\\n"
@ -168,8 +172,8 @@ embedded_instances {
"text: \\\"label\\\\n" "text: \\\"label\\\\n"
"\\\"\\n" "\\\"\\n"
" \\\"\\\"\\n" " \\\"\\\"\\n"
"font: \\\"/main/default.font\\\"\\n" "font: \\\"/builtins/fonts/system_font.font\\\"\\n"
"material: \\\"/builtins/fonts/label-df.material\\\"\\n" "material: \\\"/builtins/fonts/label.material\\\"\\n"
"\"\n" "\"\n"
" position {\n" " position {\n"
" x: 90.0\n" " x: 90.0\n"

View File

@ -3,6 +3,7 @@ local function stop_capture(self)
if self.cameraframe == nil then if self.cameraframe == nil then
return return
end end
self.cameraframe = nil self.cameraframe = nil
camera.stop_capture() camera.stop_capture()
@ -23,7 +24,7 @@ local function start_capture(self)
type = camera.CAMERA_TYPE_BACK type = camera.CAMERA_TYPE_BACK
quality = camera.CAPTURE_QUALITY_MEDIUM quality = camera.CAPTURE_QUALITY_MEDIUM
end end
camera.start_capture(type, quality, function(self, status) camera.start_capture(type, quality, function(self, status)
if status == camera.CAMERA_STARTED then if status == camera.CAMERA_STARTED then
self.cameraframe = camera.get_frame() self.cameraframe = camera.get_frame()