mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2026-01-09 09:06:53 +00:00
初始化
This commit is contained in:
217
cocos2d-x/cocos/platform/CCApplication.h
Normal file
217
cocos2d-x/cocos/platform/CCApplication.h
Normal file
@@ -0,0 +1,217 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "base/ccMacros.h"
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#include "platform/CCPlatformDefine.h"
|
||||
#include "base/CCRenderTexture.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
class Scheduler;
|
||||
|
||||
/**
|
||||
* @addtogroup platform
|
||||
* @{
|
||||
*/
|
||||
|
||||
class CC_DLL Application
|
||||
{
|
||||
public:
|
||||
|
||||
/** Since WINDOWS and ANDROID are defined as macros, we could not just use these keywords in enumeration(Platform).
|
||||
* Therefore, 'OS_' prefix is added to avoid conflicts with the definitions of system macros.
|
||||
*/
|
||||
enum class Platform
|
||||
{
|
||||
WINDOWS, /**< Windows */
|
||||
LINUX, /**< Linux */
|
||||
MAC, /**< Mac OS X*/
|
||||
ANDROIDOS, /**< Android, because ANDROID is a macro, so use ANDROIDOS instead */
|
||||
IPHONE, /**< iPhone */
|
||||
IPAD, /**< iPad */
|
||||
};
|
||||
|
||||
enum class LanguageType
|
||||
{
|
||||
ENGLISH = 0,
|
||||
CHINESE,
|
||||
FRENCH,
|
||||
ITALIAN,
|
||||
GERMAN,
|
||||
SPANISH,
|
||||
DUTCH,
|
||||
RUSSIAN,
|
||||
KOREAN,
|
||||
JAPANESE,
|
||||
HUNGARIAN,
|
||||
PORTUGUESE,
|
||||
ARABIC,
|
||||
NORWEGIAN,
|
||||
POLISH,
|
||||
TURKISH,
|
||||
UKRAINIAN,
|
||||
ROMANIAN,
|
||||
BULGARIAN
|
||||
};
|
||||
|
||||
enum class PixelFormat
|
||||
{
|
||||
RGB8,
|
||||
RGB565,
|
||||
RGBA8
|
||||
};
|
||||
|
||||
enum class DepthFormat
|
||||
{
|
||||
NONE, // no depth and no stencil
|
||||
DEPTH_COMPONENT16,
|
||||
DEPTH_COMPONENT24,
|
||||
DEPTH_COMPONENT32F,
|
||||
DEPTH24_STENCIL8,
|
||||
DEPTH32F_STENCIL8,
|
||||
STENCIL_INDEX8
|
||||
};
|
||||
|
||||
// This class is useful for internal usage.
|
||||
static Application* getInstance() { return _instance; }
|
||||
|
||||
Application(const std::string& name, int width, int height);
|
||||
virtual ~Application();
|
||||
|
||||
virtual bool applicationDidFinishLaunching();
|
||||
virtual void onPause();
|
||||
virtual void onResume();
|
||||
|
||||
inline void* getView() const { return _view; }
|
||||
inline std::shared_ptr<Scheduler> getScheduler() const { return _scheduler; }
|
||||
inline RenderTexture* getRenderTexture() const { return _renderTexture; }
|
||||
|
||||
void runOnMainThread();
|
||||
|
||||
void start();
|
||||
void restart();
|
||||
void end();
|
||||
|
||||
/**
|
||||
* @brief Sets the preferred frame rate for main loop callback.
|
||||
* @param fps The preferred frame rate for main loop callback.
|
||||
*/
|
||||
void setPreferredFramesPerSecond(int fps);
|
||||
|
||||
void setMultitouch(bool value);
|
||||
|
||||
/**
|
||||
@brief Get current language config.
|
||||
@return Current language config.
|
||||
*/
|
||||
LanguageType getCurrentLanguage() const;
|
||||
|
||||
/**
|
||||
@brief Get current language iso 639-1 code.
|
||||
@return Current language iso 639-1 code.
|
||||
*/
|
||||
std::string getCurrentLanguageCode() const;
|
||||
|
||||
const cocos2d::Vec2& getViewSize() const;
|
||||
void updateViewSize(int width, int height);
|
||||
|
||||
/**
|
||||
@brief Get current display stats.
|
||||
@return bool, is displaying stats or not.
|
||||
*/
|
||||
bool isDisplayStats();
|
||||
|
||||
/**
|
||||
@brief set display stats information.
|
||||
*/
|
||||
void setDisplayStats(bool isShow);
|
||||
|
||||
void setDevicePixelRatio(uint8_t ratio)
|
||||
{
|
||||
if (ratio <= 1)
|
||||
return;
|
||||
|
||||
_devicePixelRatio = ratio;
|
||||
_isDownsampleEnabled = true;
|
||||
_renderTexture->init(ratio);
|
||||
}
|
||||
inline uint8_t getDevicePixelRatio() const { return _devicePixelRatio; }
|
||||
inline bool isDownsampleEnabled() const { return _isDownsampleEnabled; }
|
||||
|
||||
/** The value is (framebuffer size) / (window size), but on iOS, it is special, its value is 1.
|
||||
*/
|
||||
float getScreenScale() const;
|
||||
|
||||
GLint getMainFBO() const;
|
||||
|
||||
/**
|
||||
@brief Get target platform.
|
||||
*/
|
||||
Platform getPlatform() const;
|
||||
|
||||
/**
|
||||
@brief Open url in default browser.
|
||||
@param String with url to open.
|
||||
@return True if the resource located by the URL was successfully opened; otherwise false.
|
||||
*/
|
||||
bool openURL(const std::string &url);
|
||||
|
||||
void copyTextToClipboard(const std::string &text);
|
||||
|
||||
std::string getSystemVersion();
|
||||
|
||||
protected:
|
||||
virtual void onCreateView(PixelFormat& pixelformat, DepthFormat& depthFormat, int& multisamplingCount);
|
||||
|
||||
private:
|
||||
void createView(const std::string& name, int width, int height);
|
||||
|
||||
static Application* _instance;
|
||||
static std::shared_ptr<Scheduler> _scheduler;
|
||||
|
||||
void* _view = nullptr;
|
||||
void* _delegate = nullptr;
|
||||
RenderTexture* _renderTexture = nullptr;
|
||||
int _fps = 60;
|
||||
GLint _mainFBO = 0;
|
||||
|
||||
// The ratio to downsample, for example, if its value is 2,
|
||||
// then the rendering size of render texture is device_resolution/2.
|
||||
uint8_t _devicePixelRatio = 1;
|
||||
bool _multiTouch = false;
|
||||
bool _isStarted = false;
|
||||
bool _isDownsampleEnabled = false;
|
||||
|
||||
cocos2d::Vec2 _viewSize;
|
||||
};
|
||||
|
||||
// end of platform group
|
||||
/** @} */
|
||||
|
||||
NS_CC_END
|
||||
141
cocos2d-x/cocos/platform/CCCanvasRenderingContext2D.h
Normal file
141
cocos2d-x/cocos/platform/CCCanvasRenderingContext2D.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/ccMacros.h"
|
||||
#include "base/CCData.h"
|
||||
#include "math/CCGeometry.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef OBJC_CLASS
|
||||
#ifdef __OBJC__
|
||||
#define OBJC_CLASS(name) @class name
|
||||
#else
|
||||
#define OBJC_CLASS(name) class name
|
||||
#endif
|
||||
#endif // OBJC_CLASS
|
||||
|
||||
OBJC_CLASS(CanvasRenderingContext2DImpl);
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
class CC_DLL CanvasGradient
|
||||
{
|
||||
public:
|
||||
CanvasGradient();
|
||||
~CanvasGradient();
|
||||
void addColorStop(float offset, const std::string& color);
|
||||
};
|
||||
|
||||
class CC_DLL CanvasRenderingContext2D
|
||||
{
|
||||
public:
|
||||
CanvasRenderingContext2D(float width, float height);
|
||||
~CanvasRenderingContext2D();
|
||||
|
||||
// Rect
|
||||
void rect(float x, float y, float width, float height);
|
||||
void clearRect(float x, float y, float width, float height);
|
||||
void fillRect(float x, float y, float width, float height);
|
||||
|
||||
void fillText(const std::string& text, float x, float y, float maxWidth = -1.0f);
|
||||
void strokeText(const std::string& text, float x, float y, float maxWidth = -1.0f);
|
||||
Size measureText(const std::string& text);
|
||||
CanvasGradient* createLinearGradient(float x0, float y0, float x1, float y1);
|
||||
void save();
|
||||
// Paths
|
||||
void beginPath();
|
||||
void closePath();
|
||||
void moveTo(float x, float y);
|
||||
void lineTo(float x, float y);
|
||||
void fill();
|
||||
void stroke();
|
||||
void restore();
|
||||
|
||||
// callback
|
||||
using CanvasBufferUpdatedCallback = std::function<void(const Data&)>;
|
||||
void setCanvasBufferUpdatedCallback(const CanvasBufferUpdatedCallback& cb);
|
||||
void setPremultiply(bool multiply);
|
||||
|
||||
// functions for properties
|
||||
void set__width(float width);
|
||||
void set__height(float height);
|
||||
void set_lineWidth(float lineWidth);
|
||||
void set_lineJoin(const std::string& lineJoin);
|
||||
void set_lineCap(const std::string& lineCap);
|
||||
void set_font(const std::string& font);
|
||||
void set_textAlign(const std::string& textAlign);
|
||||
void set_textBaseline(const std::string& textBaseline);
|
||||
void set_fillStyle(const std::string& fillStyle);
|
||||
void set_strokeStyle(const std::string& strokeStyle);
|
||||
void set_globalCompositeOperation(const std::string& globalCompositeOperation);
|
||||
|
||||
// fill image data into Context2D
|
||||
void _fillImageData(const Data& imageData, float imageWidth, float imageHeight, float offsetX, float offsetY);
|
||||
|
||||
// transform
|
||||
void translate(float x, float y);
|
||||
void scale(float x, float y);
|
||||
void rotate(float angle);
|
||||
|
||||
void transform(float a, float b, float c, float d, float e, float f);
|
||||
void setTransform(float a, float b, float c, float d, float e, float f);
|
||||
|
||||
private:
|
||||
void recreateBufferIfNeeded();
|
||||
|
||||
public:
|
||||
|
||||
float __width = 0.0f;
|
||||
float __height = 0.0f;
|
||||
|
||||
// Line styles
|
||||
float _lineWidth = 1.0f;
|
||||
std::string _lineJoin = "miter";
|
||||
std::string _lineCap = "butt";
|
||||
|
||||
// Text styles
|
||||
std::string _font = "10px sans-serif";
|
||||
std::string _textAlign = "start";
|
||||
std::string _textBaseline = "alphabetic";
|
||||
|
||||
// Fill and stroke styles
|
||||
std::string _fillStyle = "#000";
|
||||
std::string _strokeStyle = "#000";
|
||||
|
||||
// Compositing
|
||||
std::string _globalCompositeOperation = "source-over";
|
||||
|
||||
private:
|
||||
|
||||
CanvasBufferUpdatedCallback _canvasBufferUpdatedCB = nullptr;
|
||||
CanvasRenderingContext2DImpl* _impl = nullptr;
|
||||
|
||||
bool _isBufferSizeDirty = true;
|
||||
bool _premultiply = false;
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
154
cocos2d-x/cocos/platform/CCDevice.h
Normal file
154
cocos2d-x/cocos/platform/CCDevice.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __CCDEVICE_H__
|
||||
#define __CCDEVICE_H__
|
||||
|
||||
#include "base/ccMacros.h"
|
||||
#include "base/CCData.h"
|
||||
#include "math/Vec4.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
struct FontDefinition;
|
||||
|
||||
/**
|
||||
* @addtogroup platform
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @class Device
|
||||
* @brief
|
||||
*/
|
||||
class CC_DLL Device
|
||||
{
|
||||
public:
|
||||
enum class Rotation {
|
||||
_0 = 0,
|
||||
_90,
|
||||
_180,
|
||||
_270
|
||||
};
|
||||
|
||||
struct MotionValue {
|
||||
float accelerationX = 0.0f;
|
||||
float accelerationY = 0.0f;
|
||||
float accelerationZ = 0.0f;
|
||||
|
||||
float accelerationIncludingGravityX = 0.0f;
|
||||
float accelerationIncludingGravityY = 0.0f;
|
||||
float accelerationIncludingGravityZ = 0.0f;
|
||||
|
||||
float rotationRateAlpha = 0.0f;
|
||||
float rotationRateBeta = 0.0f;
|
||||
float rotationRateGamma = 0.0f;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the DPI of device
|
||||
* @return The DPI of device.
|
||||
*/
|
||||
static int getDPI();
|
||||
|
||||
/**
|
||||
* To enable or disable accelerometer.
|
||||
*/
|
||||
static void setAccelerometerEnabled(bool isEnabled);
|
||||
|
||||
/**
|
||||
* Sets the interval of accelerometer.
|
||||
*/
|
||||
static void setAccelerometerInterval(float interval);
|
||||
|
||||
/**
|
||||
* Gets the motion value of current device.
|
||||
*/
|
||||
static const MotionValue& getDeviceMotionValue();
|
||||
|
||||
/**
|
||||
* Gets the rotation of device.
|
||||
*/
|
||||
static Rotation getDeviceRotation();
|
||||
|
||||
/**
|
||||
* Gets device model information.
|
||||
*/
|
||||
static std::string getDeviceModel();
|
||||
|
||||
/**
|
||||
* Get device pixel ratio.
|
||||
*/
|
||||
static int getDevicePixelRatio();
|
||||
|
||||
/**
|
||||
* Controls whether the screen should remain on.
|
||||
*
|
||||
* @param keepScreenOn One flag indicating that the screen should remain on.
|
||||
*/
|
||||
static void setKeepScreenOn(bool keepScreenOn);
|
||||
|
||||
/**
|
||||
* Vibrate for the specified amount of time.
|
||||
* If vibrate is not supported, then invoking this method has no effect.
|
||||
* Some platforms limit to a maximum duration of 5 seconds.
|
||||
* Duration is ignored on iOS due to API limitations.
|
||||
* @param duration The duration in seconds.
|
||||
*/
|
||||
static void vibrate(float duration);
|
||||
|
||||
/**
|
||||
* Gets battery level, only avaiable on iOS and Android.
|
||||
* @return 0.0 ~ 1.0
|
||||
*/
|
||||
static float getBatteryLevel();
|
||||
|
||||
enum class NetworkType
|
||||
{
|
||||
NONE,
|
||||
LAN,
|
||||
WWAN
|
||||
};
|
||||
|
||||
static NetworkType getNetworkType();
|
||||
|
||||
/*
|
||||
* Gets the SafeArea edge.
|
||||
* Vec4(x, y, z, w) means Edge(top, left, bottom, right)
|
||||
*/
|
||||
static cocos2d::Vec4 getSafeAreaEdge();
|
||||
|
||||
private:
|
||||
Device();
|
||||
CC_DISALLOW_COPY_AND_ASSIGN(Device);
|
||||
};
|
||||
|
||||
// end group
|
||||
/// @}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif /* __CCDEVICE_H__ */
|
||||
1503
cocos2d-x/cocos/platform/CCFileUtils.cpp
Normal file
1503
cocos2d-x/cocos/platform/CCFileUtils.cpp
Normal file
File diff suppressed because it is too large
Load Diff
784
cocos2d-x/cocos/platform/CCFileUtils.h
Normal file
784
cocos2d-x/cocos/platform/CCFileUtils.h
Normal file
@@ -0,0 +1,784 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2013 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#ifndef __CC_FILEUTILS_H__
|
||||
#define __CC_FILEUTILS_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <type_traits>
|
||||
|
||||
#include "base/ccMacros.h"
|
||||
#include "base/ccTypes.h"
|
||||
#include "base/CCValue.h"
|
||||
#include "base/CCData.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
/**
|
||||
* @addtogroup platform
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
class ResizableBuffer {
|
||||
public:
|
||||
virtual ~ResizableBuffer() {}
|
||||
virtual void resize(size_t size) = 0;
|
||||
virtual void* buffer() const = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class ResizableBufferAdapter { };
|
||||
|
||||
|
||||
template<typename CharT, typename Traits, typename Allocator>
|
||||
class ResizableBufferAdapter< std::basic_string<CharT, Traits, Allocator> > : public ResizableBuffer {
|
||||
typedef std::basic_string<CharT, Traits, Allocator> BufferType;
|
||||
BufferType* _buffer;
|
||||
public:
|
||||
explicit ResizableBufferAdapter(BufferType* buffer) : _buffer(buffer) {}
|
||||
virtual void resize(size_t size) override {
|
||||
_buffer->resize((size + sizeof(CharT) - 1) / sizeof(CharT));
|
||||
}
|
||||
virtual void* buffer() const override {
|
||||
// can not invoke string::front() if it is empty
|
||||
|
||||
if (_buffer->empty())
|
||||
return nullptr;
|
||||
else
|
||||
return &_buffer->front();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename Allocator>
|
||||
class ResizableBufferAdapter< std::vector<T, Allocator> > : public ResizableBuffer {
|
||||
typedef std::vector<T, Allocator> BufferType;
|
||||
BufferType* _buffer;
|
||||
public:
|
||||
explicit ResizableBufferAdapter(BufferType* buffer) : _buffer(buffer) {}
|
||||
virtual void resize(size_t size) override {
|
||||
_buffer->resize((size + sizeof(T) - 1) / sizeof(T));
|
||||
}
|
||||
virtual void* buffer() const override {
|
||||
// can not invoke vector::front() if it is empty
|
||||
|
||||
if (_buffer->empty())
|
||||
return nullptr;
|
||||
else
|
||||
return &_buffer->front();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
class ResizableBufferAdapter<Data> : public ResizableBuffer {
|
||||
typedef Data BufferType;
|
||||
BufferType* _buffer;
|
||||
public:
|
||||
explicit ResizableBufferAdapter(BufferType* buffer) : _buffer(buffer) {}
|
||||
virtual void resize(size_t size) override {
|
||||
size_t oldSize = static_cast<size_t>(_buffer->getSize());
|
||||
if (oldSize != size) {
|
||||
// need to take buffer ownership for outer memory control
|
||||
auto old = _buffer->takeBuffer();
|
||||
void* buffer = realloc(old, size);
|
||||
if (buffer)
|
||||
_buffer->fastSet((unsigned char*)buffer, size);
|
||||
}
|
||||
}
|
||||
virtual void* buffer() const override {
|
||||
return _buffer->getBytes();
|
||||
}
|
||||
};
|
||||
|
||||
/** Helper class to handle file operations. */
|
||||
class CC_DLL FileUtils
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Gets the instance of FileUtils.
|
||||
*/
|
||||
static FileUtils* getInstance();
|
||||
|
||||
/**
|
||||
* Destroys the instance of FileUtils.
|
||||
*/
|
||||
static void destroyInstance();
|
||||
|
||||
/**
|
||||
* You can inherit from platform dependent implementation of FileUtils, such as FileUtilsAndroid,
|
||||
* and use this function to set delegate, then FileUtils will invoke delegate's implementation.
|
||||
* For example, your resources are encrypted, so you need to decrypt it after reading data from
|
||||
* resources, then you can implement all getXXX functions, and engine will invoke your own getXX
|
||||
* functions when reading data of resources.
|
||||
*
|
||||
* If you don't want to system default implementation after setting delegate, you can just pass nullptr
|
||||
* to this function.
|
||||
*
|
||||
* @warning It will delete previous delegate
|
||||
* @lua NA
|
||||
*/
|
||||
static void setDelegate(FileUtils *delegate);
|
||||
|
||||
/**
|
||||
* The destructor of FileUtils.
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
virtual ~FileUtils();
|
||||
|
||||
/**
|
||||
* Purges full path caches.
|
||||
*/
|
||||
virtual void purgeCachedEntries();
|
||||
|
||||
/**
|
||||
* Gets string from a file.
|
||||
*/
|
||||
virtual std::string getStringFromFile(const std::string& filename);
|
||||
|
||||
/**
|
||||
* Creates binary data from a file.
|
||||
* @return A data object.
|
||||
*/
|
||||
virtual Data getDataFromFile(const std::string& filename);
|
||||
|
||||
|
||||
enum class Status
|
||||
{
|
||||
OK = 0,
|
||||
NotExists = 1, // File not exists
|
||||
OpenFailed = 2, // Open file failed.
|
||||
ReadFailed = 3, // Read failed
|
||||
NotInitialized = 4, // FileUtils is not initializes
|
||||
TooLarge = 5, // The file is too large (great than 2^32-1)
|
||||
ObtainSizeFailed = 6 // Failed to obtain the file size.
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets whole file contents as string from a file.
|
||||
*
|
||||
* Unlike getStringFromFile, these getContents methods:
|
||||
* - read file in binary mode (does not convert CRLF to LF).
|
||||
* - does not truncate the string when '\0' is found (returned string of getContents may have '\0' in the middle.).
|
||||
*
|
||||
* The template version of can accept cocos2d::Data, std::basic_string and std::vector.
|
||||
*
|
||||
* @code
|
||||
* std::string sbuf;
|
||||
* FileUtils::getInstance()->getContents("path/to/file", &sbuf);
|
||||
*
|
||||
* std::vector<int> vbuf;
|
||||
* FileUtils::getInstance()->getContents("path/to/file", &vbuf);
|
||||
*
|
||||
* Data dbuf;
|
||||
* FileUtils::getInstance()->getContents("path/to/file", &dbuf);
|
||||
* @endcode
|
||||
*
|
||||
* Note: if you read to std::vector<T> and std::basic_string<T> where T is not 8 bit type,
|
||||
* you may get 0 ~ sizeof(T)-1 bytes padding.
|
||||
*
|
||||
* - To write a new buffer class works with getContents, just extend ResizableBuffer.
|
||||
* - To write a adapter for existing class, write a specialized ResizableBufferAdapter for that class, see follow code.
|
||||
*
|
||||
* @code
|
||||
* NS_CC_BEGIN // ResizableBufferAdapter needed in cocos2d namespace.
|
||||
* template<>
|
||||
* class ResizableBufferAdapter<AlreadyExistsBuffer> : public ResizableBuffer {
|
||||
* public:
|
||||
* ResizableBufferAdapter(AlreadyExistsBuffer* buffer) {
|
||||
* // your code here
|
||||
* }
|
||||
* virtual void resize(size_t size) override {
|
||||
* // your code here
|
||||
* }
|
||||
* virtual void* buffer() const override {
|
||||
* // your code here
|
||||
* }
|
||||
* };
|
||||
* NS_CC_END
|
||||
* @endcode
|
||||
*
|
||||
* @param[in] filename The resource file name which contains the path.
|
||||
* @param[out] buffer The buffer where the file contents are store to.
|
||||
* @return Returns:
|
||||
* - Status::OK when there is no error, the buffer is filled with the contents of file.
|
||||
* - Status::NotExists when file not exists, the buffer will not changed.
|
||||
* - Status::OpenFailed when cannot open file, the buffer will not changed.
|
||||
* - Status::ReadFailed when read end up before read whole, the buffer will fill with already read bytes.
|
||||
* - Status::NotInitialized when FileUtils is not initializes, the buffer will not changed.
|
||||
* - Status::TooLarge when there file to be read is too large (> 2^32-1), the buffer will not changed.
|
||||
* - Status::ObtainSizeFailed when failed to obtain the file size, the buffer will not changed.
|
||||
*/
|
||||
template <
|
||||
typename T,
|
||||
typename Enable = typename std::enable_if<
|
||||
std::is_base_of< ResizableBuffer, ResizableBufferAdapter<T> >::value
|
||||
>::type
|
||||
>
|
||||
Status getContents(const std::string& filename, T* buffer) {
|
||||
ResizableBufferAdapter<T> buf(buffer);
|
||||
return getContents(filename, &buf);
|
||||
}
|
||||
virtual Status getContents(const std::string& filename, ResizableBuffer* buffer);
|
||||
|
||||
/**
|
||||
* Gets resource file data
|
||||
*
|
||||
* @param[in] filename The resource file name which contains the path.
|
||||
* @param[in] mode The read mode of the file.
|
||||
* @param[out] size If the file read operation succeeds, it will be the data size, otherwise 0.
|
||||
* @return Upon success, a pointer to the data is returned, otherwise NULL.
|
||||
* @warning Recall: you are responsible for calling free() on any Non-NULL pointer returned.
|
||||
*/
|
||||
CC_DEPRECATED_ATTRIBUTE virtual unsigned char* getFileData(const std::string& filename, const char* mode, ssize_t *size);
|
||||
|
||||
/**
|
||||
* Gets resource file data from a zip file.
|
||||
*
|
||||
* @param[in] filename The resource file name which contains the relative path of the zip file.
|
||||
* @param[out] size If the file read operation succeeds, it will be the data size, otherwise 0.
|
||||
* @return Upon success, a pointer to the data is returned, otherwise nullptr.
|
||||
* @warning Recall: you are responsible for calling free() on any Non-nullptr pointer returned.
|
||||
*/
|
||||
virtual unsigned char* getFileDataFromZip(const std::string& zipFilePath, const std::string& filename, ssize_t *size);
|
||||
|
||||
|
||||
/** Returns the fullpath for a given filename.
|
||||
|
||||
First it will try to get a new filename from the "filenameLookup" dictionary.
|
||||
If a new filename can't be found on the dictionary, it will use the original filename.
|
||||
Then it will try to obtain the full path of the filename using the FileUtils search rules: resolutions, and search paths.
|
||||
The file search is based on the array element order of search paths and resolution directories.
|
||||
|
||||
For instance:
|
||||
|
||||
We set two elements("/mnt/sdcard/", "internal_dir/") to search paths vector by setSearchPaths,
|
||||
and set three elements("resources-ipadhd/", "resources-ipad/", "resources-iphonehd")
|
||||
to resolutions vector by setSearchResolutionsOrder. The "internal_dir" is relative to "Resources/".
|
||||
|
||||
If we have a file named 'sprite.png', the mapping in fileLookup dictionary contains `key: sprite.png -> value: sprite.pvr.gz`.
|
||||
Firstly, it will replace 'sprite.png' with 'sprite.pvr.gz', then searching the file sprite.pvr.gz as follows:
|
||||
|
||||
/mnt/sdcard/resources-ipadhd/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/resources-ipad/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/resources-iphonehd/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/resources-ipadhd/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/resources-ipad/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/resources-iphonehd/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/sprite.pvr.gz (if not found, return "sprite.png")
|
||||
|
||||
If the filename contains relative path like "gamescene/uilayer/sprite.png",
|
||||
and the mapping in fileLookup dictionary contains `key: gamescene/uilayer/sprite.png -> value: gamescene/uilayer/sprite.pvr.gz`.
|
||||
The file search order will be:
|
||||
|
||||
/mnt/sdcard/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/gamescene/uilayer/resources-ipad/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz (if not found, search next)
|
||||
/mnt/sdcard/gamescene/uilayer/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/gamescene/uilayer/resources-ipad/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz (if not found, search next)
|
||||
internal_dir/gamescene/uilayer/sprite.pvr.gz (if not found, return "gamescene/uilayer/sprite.png")
|
||||
|
||||
If the new file can't be found on the file system, it will return the parameter filename directly.
|
||||
|
||||
This method was added to simplify multiplatform support. Whether you are using cocos2d-js or any cross-compilation toolchain like StellaSDK or Apportable,
|
||||
you might need to load different resources for a given file in the different platforms.
|
||||
|
||||
@since v2.1
|
||||
*/
|
||||
virtual std::string fullPathForFilename(const std::string &filename) const;
|
||||
|
||||
/**
|
||||
* Loads the filenameLookup dictionary from the contents of a filename.
|
||||
*
|
||||
* @note The plist file name should follow the format below:
|
||||
*
|
||||
* @code
|
||||
* <?xml version="1.0" encoding="UTF-8"?>
|
||||
* <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
* <plist version="1.0">
|
||||
* <dict>
|
||||
* <key>filenames</key>
|
||||
* <dict>
|
||||
* <key>sounds/click.wav</key>
|
||||
* <string>sounds/click.caf</string>
|
||||
* <key>sounds/endgame.wav</key>
|
||||
* <string>sounds/endgame.caf</string>
|
||||
* <key>sounds/gem-0.wav</key>
|
||||
* <string>sounds/gem-0.caf</string>
|
||||
* </dict>
|
||||
* <key>metadata</key>
|
||||
* <dict>
|
||||
* <key>version</key>
|
||||
* <integer>1</integer>
|
||||
* </dict>
|
||||
* </dict>
|
||||
* </plist>
|
||||
* @endcode
|
||||
* @param filename The plist file name.
|
||||
*
|
||||
@since v2.1
|
||||
* @js loadFilenameLookup
|
||||
* @lua loadFilenameLookup
|
||||
*/
|
||||
virtual void loadFilenameLookupDictionaryFromFile(const std::string &filename);
|
||||
|
||||
/**
|
||||
* Sets the filenameLookup dictionary.
|
||||
*
|
||||
* @param filenameLookupDict The dictionary for replacing filename.
|
||||
* @since v2.1
|
||||
*/
|
||||
virtual void setFilenameLookupDictionary(const ValueMap& filenameLookupDict);
|
||||
|
||||
/**
|
||||
* Gets full path from a file name and the path of the relative file.
|
||||
* @param filename The file name.
|
||||
* @param relativeFile The path of the relative file.
|
||||
* @return The full path.
|
||||
* e.g. filename: hello.png, pszRelativeFile: /User/path1/path2/hello.plist
|
||||
* Return: /User/path1/path2/hello.pvr (If there a a key(hello.png)-value(hello.pvr) in FilenameLookup dictionary. )
|
||||
*
|
||||
*/
|
||||
virtual std::string fullPathFromRelativeFile(const std::string &filename, const std::string &relativeFile);
|
||||
|
||||
/**
|
||||
* Sets the array that contains the search order of the resources.
|
||||
*
|
||||
* @param searchResolutionsOrder The source array that contains the search order of the resources.
|
||||
* @see getSearchResolutionsOrder(), fullPathForFilename(const char*).
|
||||
* @since v2.1
|
||||
* In js:var setSearchResolutionsOrder(var jsval)
|
||||
* @lua NA
|
||||
*/
|
||||
virtual void setSearchResolutionsOrder(const std::vector<std::string>& searchResolutionsOrder);
|
||||
|
||||
/**
|
||||
* Append search order of the resources.
|
||||
*
|
||||
* @see setSearchResolutionsOrder(), fullPathForFilename().
|
||||
* @since v2.1
|
||||
*/
|
||||
virtual void addSearchResolutionsOrder(const std::string &order,const bool front=false);
|
||||
|
||||
/**
|
||||
* Gets the array that contains the search order of the resources.
|
||||
*
|
||||
* @see setSearchResolutionsOrder(const std::vector<std::string>&), fullPathForFilename(const char*).
|
||||
* @since v2.1
|
||||
* @lua NA
|
||||
*/
|
||||
virtual const std::vector<std::string>& getSearchResolutionsOrder() const;
|
||||
|
||||
/**
|
||||
* Sets the array of search paths.
|
||||
*
|
||||
* You can use this array to modify the search path of the resources.
|
||||
* If you want to use "themes" or search resources in the "cache", you can do it easily by adding new entries in this array.
|
||||
*
|
||||
* @note This method could access relative path and absolute path.
|
||||
* If the relative path was passed to the vector, FileUtils will add the default resource directory before the relative path.
|
||||
* For instance:
|
||||
* On Android, the default resource root path is "@assets/".
|
||||
* If "/mnt/sdcard/" and "resources-large" were set to the search paths vector,
|
||||
* "resources-large" will be converted to "@assets/resources-large" since it was a relative path.
|
||||
*
|
||||
* @param searchPaths The array contains search paths.
|
||||
* @see fullPathForFilename(const char*)
|
||||
* @since v2.1
|
||||
* In js:var setSearchPaths(var jsval);
|
||||
* @lua NA
|
||||
*/
|
||||
virtual void setSearchPaths(const std::vector<std::string>& searchPaths);
|
||||
|
||||
/**
|
||||
* Get default resource root path.
|
||||
*/
|
||||
const std::string& getDefaultResourceRootPath() const;
|
||||
|
||||
/**
|
||||
* Set default resource root path.
|
||||
*/
|
||||
void setDefaultResourceRootPath(const std::string& path);
|
||||
|
||||
/**
|
||||
* Add search path.
|
||||
*
|
||||
* @since v2.1
|
||||
*/
|
||||
void addSearchPath(const std::string & path, const bool front=false);
|
||||
|
||||
/**
|
||||
* Gets the array of search paths.
|
||||
*
|
||||
* @return The array of search paths which may contain the prefix of default resource root path.
|
||||
* @note In best practise, getter function should return the value of setter function passes in.
|
||||
* But since we should not break the compatibility, we keep using the old logic.
|
||||
* Therefore, If you want to get the original search paths, please call 'getOriginalSearchPaths()' instead.
|
||||
* @see fullPathForFilename(const char*).
|
||||
* @lua NA
|
||||
*/
|
||||
virtual const std::vector<std::string>& getSearchPaths() const;
|
||||
|
||||
/**
|
||||
* Gets the original search path array set by 'setSearchPaths' or 'addSearchPath'.
|
||||
* @return The array of the original search paths
|
||||
*/
|
||||
virtual const std::vector<std::string>& getOriginalSearchPaths() const;
|
||||
|
||||
/**
|
||||
* Gets the writable path.
|
||||
* @return The path that can be write/read a file in
|
||||
*/
|
||||
virtual std::string getWritablePath() const = 0;
|
||||
|
||||
/**
|
||||
* Sets writable path.
|
||||
*/
|
||||
virtual void setWritablePath(const std::string& writablePath);
|
||||
|
||||
/**
|
||||
* Sets whether to pop-up a message box when failed to load an image.
|
||||
*/
|
||||
virtual void setPopupNotify(bool notify);
|
||||
|
||||
/** Checks whether to pop up a message box when failed to load an image.
|
||||
* @return True if pop up a message box when failed to load an image, false if not.
|
||||
*/
|
||||
virtual bool isPopupNotify() const;
|
||||
|
||||
/**
|
||||
* Converts the contents of a file to a ValueMap.
|
||||
* @param filename The filename of the file to gets content.
|
||||
* @return ValueMap of the file contents.
|
||||
* @note This method is used internally.
|
||||
*/
|
||||
virtual ValueMap getValueMapFromFile(const std::string& filename);
|
||||
|
||||
|
||||
/** Converts the contents of a file to a ValueMap.
|
||||
* This method is used internally.
|
||||
*/
|
||||
virtual ValueMap getValueMapFromData(const char* filedata, int filesize);
|
||||
|
||||
/**
|
||||
* write a ValueMap into a plist file
|
||||
*
|
||||
*@param dict the ValueMap want to save
|
||||
*@param fullPath The full path to the file you want to save a string
|
||||
*@return bool
|
||||
*/
|
||||
virtual bool writeToFile(const ValueMap& dict, const std::string& fullPath);
|
||||
|
||||
/**
|
||||
* write a string into a file
|
||||
*
|
||||
* @param dataStr the string want to save
|
||||
* @param fullPath The full path to the file you want to save a string
|
||||
* @return bool True if write success
|
||||
*/
|
||||
virtual bool writeStringToFile(const std::string& dataStr, const std::string& fullPath);
|
||||
|
||||
|
||||
/**
|
||||
* write Data into a file
|
||||
*
|
||||
*@param data the data want to save
|
||||
*@param fullPath The full path to the file you want to save a string
|
||||
*@return bool
|
||||
*/
|
||||
virtual bool writeDataToFile(const Data& data, const std::string& fullPath);
|
||||
|
||||
/**
|
||||
* write ValueMap into a plist file
|
||||
*
|
||||
*@param dict the ValueMap want to save
|
||||
*@param fullPath The full path to the file you want to save a string
|
||||
*@return bool
|
||||
*/
|
||||
virtual bool writeValueMapToFile(const ValueMap& dict, const std::string& fullPath);
|
||||
|
||||
/**
|
||||
* write ValueVector into a plist file
|
||||
*
|
||||
*@param vecData the ValueVector want to save
|
||||
*@param fullPath The full path to the file you want to save a string
|
||||
*@return bool
|
||||
*/
|
||||
virtual bool writeValueVectorToFile(const ValueVector& vecData, const std::string& fullPath);
|
||||
|
||||
/**
|
||||
* Windows fopen can't support UTF-8 filename
|
||||
* Need convert all parameters fopen and other 3rd-party libs
|
||||
*
|
||||
* @param filenameUtf8 std::string name file for conversion from utf-8
|
||||
* @return std::string ansi filename in current locale
|
||||
*/
|
||||
virtual std::string getSuitableFOpen(const std::string& filenameUtf8) const;
|
||||
|
||||
// Converts the contents of a file to a ValueVector.
|
||||
// This method is used internally.
|
||||
virtual ValueVector getValueVectorFromFile(const std::string& filename);
|
||||
|
||||
/**
|
||||
* Checks whether a file exists.
|
||||
*
|
||||
* @note If a relative path was passed in, it will be inserted a default root path at the beginning.
|
||||
* @param filename The path of the file, it could be a relative or absolute path.
|
||||
* @return True if the file exists, false if not.
|
||||
*/
|
||||
virtual bool isFileExist(const std::string& filename) const;
|
||||
|
||||
/**
|
||||
* Gets filename extension is a suffix (separated from the base filename by a dot) in lower case.
|
||||
* Examples of filename extensions are .png, .jpeg, .exe, .dmg and .txt.
|
||||
* @param filePath The path of the file, it could be a relative or absolute path.
|
||||
* @return suffix for filename in lower case or empty if a dot not found.
|
||||
*/
|
||||
virtual std::string getFileExtension(const std::string& filePath) const;
|
||||
|
||||
/**
|
||||
* Checks whether the path is an absolute path.
|
||||
*
|
||||
* @note On Android, if the parameter passed in is relative to "@assets/", this method will treat it as an absolute path.
|
||||
* Also on Blackberry, path starts with "app/native/Resources/" is treated as an absolute path.
|
||||
*
|
||||
* @param path The path that needs to be checked.
|
||||
* @return True if it's an absolute path, false if not.
|
||||
*/
|
||||
virtual bool isAbsolutePath(const std::string& path) const;
|
||||
|
||||
/**
|
||||
* Checks whether the path is a directory.
|
||||
*
|
||||
* @param dirPath The path of the directory, it could be a relative or an absolute path.
|
||||
* @return True if the directory exists, false if not.
|
||||
*/
|
||||
virtual bool isDirectoryExist(const std::string& dirPath) const;
|
||||
|
||||
/**
|
||||
* List all files in a directory.
|
||||
*
|
||||
* @param dirPath The path of the directory, it could be a relative or an absolute path.
|
||||
* @return File paths in a string vector
|
||||
*/
|
||||
virtual std::vector<std::string> listFiles(const std::string& dirPath) const;
|
||||
|
||||
/**
|
||||
* List all files recursively in a directory.
|
||||
*
|
||||
* @param dirPath The path of the directory, it could be a relative or an absolute path.
|
||||
* @return File paths in a string vector
|
||||
*/
|
||||
virtual void listFilesRecursively(const std::string& dirPath, std::vector<std::string> *files) const;
|
||||
|
||||
/**
|
||||
* Creates a directory.
|
||||
*
|
||||
* @param dirPath The path of the directory, it must be an absolute path.
|
||||
* @return True if the directory have been created successfully, false if not.
|
||||
*/
|
||||
virtual bool createDirectory(const std::string& dirPath);
|
||||
|
||||
/**
|
||||
* Removes a directory.
|
||||
*
|
||||
* @param dirPath The full path of the directory, it must be an absolute path.
|
||||
* @return True if the directory have been removed successfully, false if not.
|
||||
*/
|
||||
virtual bool removeDirectory(const std::string& dirPath);
|
||||
|
||||
/**
|
||||
* Removes a file.
|
||||
*
|
||||
* @param filepath The full path of the file, it must be an absolute path.
|
||||
* @return True if the file have been removed successfully, false if not.
|
||||
*/
|
||||
virtual bool removeFile(const std::string &filepath);
|
||||
|
||||
/**
|
||||
* Renames a file under the given directory.
|
||||
*
|
||||
* @param path The parent directory path of the file, it must be an absolute path.
|
||||
* @param oldname The current name of the file.
|
||||
* @param name The new name of the file.
|
||||
* @return True if the file have been renamed successfully, false if not.
|
||||
*/
|
||||
virtual bool renameFile(const std::string &path, const std::string &oldname, const std::string &name);
|
||||
|
||||
/**
|
||||
* Renames a file under the given directory.
|
||||
*
|
||||
* @param oldfullpath The current fullpath of the file. Includes path and name.
|
||||
* @param newfullpath The new fullpath of the file. Includes path and name.
|
||||
* @return True if the file have been renamed successfully, false if not.
|
||||
*/
|
||||
virtual bool renameFile(const std::string &oldfullpath, const std::string &newfullpath);
|
||||
|
||||
/**
|
||||
* Retrieve the file size.
|
||||
*
|
||||
* @note If a relative path was passed in, it will be inserted a default root path at the beginning.
|
||||
* @param filepath The path of the file, it could be a relative or absolute path.
|
||||
* @return The file size.
|
||||
*/
|
||||
virtual long getFileSize(const std::string &filepath);
|
||||
|
||||
/** Returns the full path cache. */
|
||||
const std::unordered_map<std::string, std::string>& getFullPathCache() const { return _fullPathCache; }
|
||||
|
||||
std::string normalizePath(const std::string& path) const;
|
||||
std::string getFileDir(const std::string& path) const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The default constructor.
|
||||
*/
|
||||
FileUtils();
|
||||
|
||||
/**
|
||||
* Initializes the instance of FileUtils. It will set _searchPathArray and _searchResolutionsOrderArray to default values.
|
||||
*
|
||||
* @note When you are porting Cocos2d-x to a new platform, you may need to take care of this method.
|
||||
* You could assign a default value to _defaultResRootPath in the subclass of FileUtils(e.g. FileUtilsAndroid). Then invoke the FileUtils::init().
|
||||
* @return true if succeed, otherwise it returns false.
|
||||
*
|
||||
*/
|
||||
virtual bool init();
|
||||
|
||||
/**
|
||||
* Gets the new filename from the filename lookup dictionary.
|
||||
* It is possible to have a override names.
|
||||
* @param filename The original filename.
|
||||
* @return The new filename after searching in the filename lookup dictionary.
|
||||
* If the original filename wasn't in the dictionary, it will return the original filename.
|
||||
*/
|
||||
virtual std::string getNewFilename(const std::string &filename) const;
|
||||
|
||||
/**
|
||||
* Checks whether a file exists without considering search paths and resolution orders.
|
||||
* @param filename The file (with absolute path) to look up for
|
||||
* @return Returns true if the file found at the given absolute path, otherwise returns false
|
||||
*/
|
||||
virtual bool isFileExistInternal(const std::string& filename) const = 0;
|
||||
|
||||
/**
|
||||
* Checks whether a directory exists without considering search paths and resolution orders.
|
||||
* @param dirPath The directory (with absolute path) to look up for
|
||||
* @return Returns true if the directory found at the given absolute path, otherwise returns false
|
||||
*/
|
||||
virtual bool isDirectoryExistInternal(const std::string& dirPath) const;
|
||||
|
||||
/**
|
||||
* Gets full path for filename, resolution directory and search path.
|
||||
*
|
||||
* @param filename The file name.
|
||||
* @param resolutionDirectory The resolution directory.
|
||||
* @param searchPath The search path.
|
||||
* @return The full path of the file. It will return an empty string if the full path of the file doesn't exist.
|
||||
*/
|
||||
virtual std::string getPathForFilename(const std::string& filename, const std::string& resolutionDirectory, const std::string& searchPath) const;
|
||||
|
||||
/**
|
||||
* Gets full path for the directory and the filename.
|
||||
*
|
||||
* @note Only iOS and Mac need to override this method since they are using
|
||||
* `[[NSBundle mainBundle] pathForResource: ofType: inDirectory:]` to make a full path.
|
||||
* Other platforms will use the default implementation of this method.
|
||||
* @param directory The directory contains the file we are looking for.
|
||||
* @param filename The name of the file.
|
||||
* @return The full path of the file, if the file can't be found, it will return an empty string.
|
||||
*/
|
||||
virtual std::string getFullPathForDirectoryAndFilename(const std::string& directory, const std::string& filename) const;
|
||||
|
||||
/** Dictionary used to lookup filenames based on a key.
|
||||
* It is used internally by the following methods:
|
||||
*
|
||||
* std::string fullPathForFilename(const char*);
|
||||
*
|
||||
* @since v2.1
|
||||
*/
|
||||
ValueMap _filenameLookupDict;
|
||||
|
||||
/**
|
||||
* The vector contains resolution folders.
|
||||
* The lower index of the element in this vector, the higher priority for this resolution directory.
|
||||
*/
|
||||
std::vector<std::string> _searchResolutionsOrderArray;
|
||||
|
||||
/**
|
||||
* The vector contains search paths.
|
||||
* The lower index of the element in this vector, the higher priority for this search path.
|
||||
*/
|
||||
std::vector<std::string> _searchPathArray;
|
||||
|
||||
/**
|
||||
* The search paths which was set by 'setSearchPaths' / 'addSearchPath'.
|
||||
*/
|
||||
std::vector<std::string> _originalSearchPaths;
|
||||
|
||||
/**
|
||||
* The default root path of resources.
|
||||
* If the default root path of resources needs to be changed, do it in the `init` method of FileUtils's subclass.
|
||||
* For instance:
|
||||
* On Android, the default root path of resources will be assigned with "@assets/" in FileUtilsAndroid::init().
|
||||
* Similarly on Blackberry, we assign "app/native/Resources/" to this variable in FileUtilsBlackberry::init().
|
||||
*/
|
||||
std::string _defaultResRootPath;
|
||||
|
||||
/**
|
||||
* The full path cache. When a file is found, it will be added into this cache.
|
||||
* This variable is used for improving the performance of file search.
|
||||
*/
|
||||
mutable std::unordered_map<std::string, std::string> _fullPathCache;
|
||||
|
||||
/**
|
||||
* Writable path.
|
||||
*/
|
||||
std::string _writablePath;
|
||||
|
||||
/**
|
||||
* The singleton pointer of FileUtils.
|
||||
*/
|
||||
static FileUtils* s_sharedFileUtils;
|
||||
|
||||
/**
|
||||
* Remove null value key (for iOS)
|
||||
*/
|
||||
virtual void valueMapCompact(ValueMap& valueMap);
|
||||
virtual void valueVectorCompact(ValueVector& valueVector);
|
||||
};
|
||||
|
||||
// end of support group
|
||||
/** @} */
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // __CC_FILEUTILS_H__
|
||||
118
cocos2d-x/cocos/platform/CCGL.h
Normal file
118
cocos2d-x/cocos/platform/CCGL.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __PLATFORM_CCGL_H__
|
||||
#define __PLATFORM_CCGL_H__
|
||||
/// @cond DO_NOT_SHOW
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
|
||||
#ifndef GL_TEXTURE_MIN_LOD
|
||||
#define GL_TEXTURE_MIN_LOD 0x813A
|
||||
#endif
|
||||
|
||||
#ifndef GL_UNPACK_FLIP_Y_WEBGL
|
||||
#define GL_UNPACK_FLIP_Y_WEBGL 0x9240
|
||||
#endif
|
||||
|
||||
#ifndef GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL
|
||||
#define GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL 0x9241
|
||||
#endif
|
||||
|
||||
#ifndef GL_CONTEXT_LOST_WEBGL
|
||||
#define GL_CONTEXT_LOST_WEBGL 0x9242
|
||||
#endif
|
||||
|
||||
#ifndef GL_UNPACK_COLORSPACE_CONVERSION_WEBGL
|
||||
#define GL_UNPACK_COLORSPACE_CONVERSION_WEBGL 0x9243
|
||||
#endif
|
||||
|
||||
#ifndef GL_BROWSER_DEFAULT_WEBGL
|
||||
#define GL_BROWSER_DEFAULT_WEBGL 0x9244
|
||||
#endif
|
||||
|
||||
#ifndef GL_DEPTH_STENCIL_ATTACHMENT
|
||||
#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
|
||||
#endif
|
||||
|
||||
/* Shader Precision-Specified Types */
|
||||
#ifndef GL_LOW_FLOAT
|
||||
#define GL_LOW_FLOAT 0x8DF0
|
||||
#endif
|
||||
|
||||
#ifndef GL_MEDIUM_FLOAT
|
||||
#define GL_MEDIUM_FLOAT 0x8DF1
|
||||
#endif
|
||||
|
||||
#ifndef GL_HIGH_FLOAT
|
||||
#define GL_HIGH_FLOAT 0x8DF2
|
||||
#endif
|
||||
|
||||
#ifndef GL_LOW_INT
|
||||
#define GL_LOW_INT 0x8DF3
|
||||
#endif
|
||||
|
||||
#ifndef GL_MEDIUM_INT
|
||||
#define GL_MEDIUM_INT 0x8DF4
|
||||
#endif
|
||||
|
||||
#ifndef GL_HIGH_INT
|
||||
#define GL_HIGH_INT 0x8DF5
|
||||
#endif
|
||||
|
||||
#ifndef GL_MAX_VERTEX_UNIFORM_VECTORS
|
||||
#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
|
||||
#endif
|
||||
|
||||
#ifndef GL_MAX_FRAGMENT_UNIFORM_VECTORS
|
||||
#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
|
||||
#endif
|
||||
|
||||
#ifndef GL_MAX_VARYING_VECTORS
|
||||
#define GL_MAX_VARYING_VECTORS 0x8DFC
|
||||
#endif
|
||||
|
||||
#ifndef GL_DEPTH_STENCIL
|
||||
#define GL_DEPTH_STENCIL 0x84F9
|
||||
#endif
|
||||
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
#include "platform/mac/CCGL-mac.h"
|
||||
#elif CC_TARGET_PLATFORM == CC_PLATFORM_IOS
|
||||
#include "platform/ios/CCGL-ios.h"
|
||||
#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||
#include "platform/android/CCGL-android.h"
|
||||
#elif CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
#include "platform/win32/CCGL-win32.h"
|
||||
#elif CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
|
||||
#include "platform/winrt/CCGL.h"
|
||||
#elif CC_TARGET_PLATFORM == CC_PLATFORM_LINUX
|
||||
#include "platform/linux/CCGL-linux.h"
|
||||
#endif
|
||||
|
||||
/// @endcond
|
||||
#endif /* __PLATFORM_CCPLATFORMDEFINE_H__*/
|
||||
|
||||
2179
cocos2d-x/cocos/platform/CCImage.cpp
Normal file
2179
cocos2d-x/cocos/platform/CCImage.cpp
Normal file
File diff suppressed because it is too large
Load Diff
311
cocos2d-x/cocos/platform/CCImage.h
Normal file
311
cocos2d-x/cocos/platform/CCImage.h
Normal file
@@ -0,0 +1,311 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __CC_IMAGE_H__
|
||||
#define __CC_IMAGE_H__
|
||||
/// @cond DO_NOT_SHOW
|
||||
|
||||
#include "base/CCRef.h"
|
||||
#include "platform/CCGL.h"
|
||||
#include "platform/CCStdC.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
// premultiply alpha, or the effect will wrong when want to use other pixel format in Texture2D,
|
||||
// such as RGB888, RGB5A1
|
||||
#define CC_RGB_PREMULTIPLY_ALPHA(vr, vg, vb, va) \
|
||||
(unsigned)(((unsigned)((unsigned char)(vr) * ((unsigned char)(va) + 1)) >> 8) | \
|
||||
((unsigned)((unsigned char)(vg) * ((unsigned char)(va) + 1) >> 8) << 8) | \
|
||||
((unsigned)((unsigned char)(vb) * ((unsigned char)(va) + 1) >> 8) << 16) | \
|
||||
((unsigned)(unsigned char)(va) << 24))
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
/**
|
||||
* @addtogroup platform
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
@brief Structure which can tell where mipmap begins and how long is it
|
||||
*/
|
||||
typedef struct _MipmapInfo
|
||||
{
|
||||
unsigned char* address = nullptr;
|
||||
int offset = 0;
|
||||
int len = 0;
|
||||
}MipmapInfo;
|
||||
|
||||
class Image : public Ref
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @js ctor
|
||||
*/
|
||||
Image();
|
||||
|
||||
/** Supported formats for Image */
|
||||
enum class Format
|
||||
{
|
||||
//! JPEG
|
||||
JPG,
|
||||
//! PNG
|
||||
PNG,
|
||||
//! TIFF
|
||||
TIFF,
|
||||
//! WebP
|
||||
WEBP,
|
||||
//! PVR
|
||||
PVR,
|
||||
//! ETC
|
||||
ETC,
|
||||
//! ETC2
|
||||
ETC2,
|
||||
//! S3TC
|
||||
S3TC,
|
||||
//! ATITC
|
||||
// ATITC,
|
||||
//! TGA
|
||||
TGA,
|
||||
//! Raw Data
|
||||
RAW_DATA,
|
||||
//! Unknown format
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
/** @typedef Texture2D::PixelFormat
|
||||
Possible texture pixel formats
|
||||
*/
|
||||
enum class PixelFormat
|
||||
{
|
||||
//! auto detect the type
|
||||
AUTO,
|
||||
//! 32-bit texture: BGRA8888
|
||||
BGRA8888,
|
||||
//! 32-bit texture: RGBA8888
|
||||
RGBA8888,
|
||||
//! 24-bit texture: RGBA888
|
||||
RGB888,
|
||||
//! 16-bit texture without Alpha channel
|
||||
RGB565,
|
||||
//! 8-bit textures used as masks
|
||||
A8,
|
||||
//! 8-bit intensity texture
|
||||
I8,
|
||||
//! 16-bit textures used as masks
|
||||
AI88,
|
||||
//! 16-bit textures: RGBA4444
|
||||
RGBA4444,
|
||||
//! 16-bit textures: RGB5A1
|
||||
RGB5A1,
|
||||
//! 4-bit PVRTC-compressed texture: PVRTC4
|
||||
PVRTC4,
|
||||
//! 4-bit PVRTC-compressed texture: PVRTC4 (has alpha channel)
|
||||
PVRTC4A,
|
||||
//! 2-bit PVRTC-compressed texture: PVRTC2
|
||||
PVRTC2,
|
||||
//! 2-bit PVRTC-compressed texture: PVRTC2 (has alpha channel)
|
||||
PVRTC2A,
|
||||
//! ETC-compressed texture: ETC
|
||||
ETC,
|
||||
//! ETC-compressed texture: GL_COMPRESSED_RGB8_ETC2
|
||||
ETC2_RGB,
|
||||
//! ETC-compressed texture: GL_COMPRESSED_RGBA8_ETC2
|
||||
ETC2_RGBA,
|
||||
//! S3TC-compressed texture: S3TC_Dxt1
|
||||
S3TC_DXT1,
|
||||
//! S3TC-compressed texture: S3TC_Dxt3
|
||||
S3TC_DXT3,
|
||||
//! S3TC-compressed texture: S3TC_Dxt5
|
||||
S3TC_DXT5,
|
||||
//! ATITC-compressed texture: ATC_RGB
|
||||
ATC_RGB,
|
||||
//! ATITC-compressed texture: ATC_EXPLICIT_ALPHA
|
||||
ATC_EXPLICIT_ALPHA,
|
||||
//! ATITC-compressed texture: ATC_INTERPOLATED_ALPHA
|
||||
ATC_INTERPOLATED_ALPHA,
|
||||
//! Default texture format: AUTO
|
||||
DEFAULT = AUTO,
|
||||
|
||||
NONE = -1
|
||||
};
|
||||
|
||||
struct PixelFormatInfo {
|
||||
|
||||
PixelFormatInfo(GLenum anInternalFormat, GLenum aFormat, GLenum aType, int aBpp, bool aCompressed, bool anAlpha)
|
||||
: internalFormat(anInternalFormat)
|
||||
, format(aFormat)
|
||||
, type(aType)
|
||||
, bpp(aBpp)
|
||||
, compressed(aCompressed)
|
||||
, alpha(anAlpha)
|
||||
{}
|
||||
|
||||
GLenum internalFormat;
|
||||
GLenum format;
|
||||
GLenum type;
|
||||
int bpp;
|
||||
bool compressed;
|
||||
bool alpha;
|
||||
};
|
||||
|
||||
typedef std::map<PixelFormat, const PixelFormatInfo> PixelFormatInfoMap;
|
||||
|
||||
/**
|
||||
* Enables or disables premultiplied alpha for PNG files.
|
||||
*
|
||||
* @param enabled (default: true)
|
||||
*/
|
||||
static void setPNGPremultipliedAlphaEnabled(bool enabled) { PNG_PREMULTIPLIED_ALPHA_ENABLED = enabled; }
|
||||
|
||||
/** treats (or not) PVR files as if they have alpha premultiplied.
|
||||
Since it is impossible to know at runtime if the PVR images have the alpha channel premultiplied, it is
|
||||
possible load them as if they have (or not) the alpha channel premultiplied.
|
||||
|
||||
By default it is disabled.
|
||||
*/
|
||||
static void setPVRImagesHavePremultipliedAlpha(bool haveAlphaPremultiplied);
|
||||
|
||||
/**
|
||||
@brief Load the image from the specified path.
|
||||
@param path the absolute file path.
|
||||
@return true if loaded correctly.
|
||||
*/
|
||||
bool initWithImageFile(const std::string& path);
|
||||
|
||||
/**
|
||||
@brief Load image from stream buffer.
|
||||
@param data stream buffer which holds the image data.
|
||||
@param dataLen data length expressed in (number of) bytes.
|
||||
@return true if loaded correctly.
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
bool initWithImageData(const unsigned char * data, ssize_t dataLen);
|
||||
|
||||
// @warning kFmtRawData only support RGBA8888
|
||||
bool initWithRawData(const unsigned char * data, ssize_t dataLen, int width, int height, int bitsPerComponent, bool preMulti = false);
|
||||
|
||||
// Getters
|
||||
inline unsigned char* getData() const { return _data; }
|
||||
inline ssize_t getDataLen() const { return _dataLen; }
|
||||
inline Format getFileType() const { return _fileType; }
|
||||
inline PixelFormat getRenderFormat() const { return _renderFormat; }
|
||||
inline int getWidth() const { return _width; }
|
||||
inline int getHeight() const { return _height; }
|
||||
inline int getNumberOfMipmaps() const { return _numberOfMipmaps; }
|
||||
inline const MipmapInfo* getMipmaps() const { return _mipmaps; }
|
||||
inline bool hasPremultipliedAlpha() const { return _hasPremultipliedAlpha; }
|
||||
inline std::string getFilePath() const { return _filePath; }
|
||||
|
||||
int getBitPerPixel() const;
|
||||
bool hasAlpha() const;
|
||||
bool isCompressed() const;
|
||||
|
||||
const PixelFormatInfo& getPixelFormatInfo() const;
|
||||
|
||||
/**
|
||||
@brief Save Image data to the specified file, with specified format.
|
||||
@param filename the file's absolute path, including file suffix.
|
||||
@param isToRGB whether the image is saved as RGB format.
|
||||
*/
|
||||
bool saveToFile(const std::string &filename, bool isToRGB = true);
|
||||
|
||||
protected:
|
||||
bool initWithJpgData(const unsigned char * data, ssize_t dataLen);
|
||||
bool initWithPngData(const unsigned char * data, ssize_t dataLen);
|
||||
bool initWithTiffData(const unsigned char * data, ssize_t dataLen);
|
||||
bool initWithWebpData(const unsigned char * data, ssize_t dataLen);
|
||||
bool initWithPVRData(const unsigned char * data, ssize_t dataLen);
|
||||
bool initWithPVRv2Data(const unsigned char * data, ssize_t dataLen);
|
||||
bool initWithPVRv3Data(const unsigned char * data, ssize_t dataLen);
|
||||
bool initWithETCData(const unsigned char * data, ssize_t dataLen);
|
||||
bool initWithETC2Data(const unsigned char * data, ssize_t dataLen);
|
||||
bool initWithS3TCData(const unsigned char * data, ssize_t dataLen);
|
||||
|
||||
typedef struct sImageTGA tImageTGA;
|
||||
bool initWithTGAData(tImageTGA* tgaData);
|
||||
|
||||
bool saveImageToPNG(const std::string& filePath, bool isToRGB = true);
|
||||
bool saveImageToJPG(const std::string& filePath);
|
||||
|
||||
void premultipliedAlpha();
|
||||
|
||||
protected:
|
||||
/**
|
||||
@brief Determine how many mipmaps can we have.
|
||||
It's same as define but it respects namespaces
|
||||
*/
|
||||
static const int MIPMAP_MAX = 16;
|
||||
/**
|
||||
@brief Determine whether we premultiply alpha for png files.
|
||||
*/
|
||||
static bool PNG_PREMULTIPLIED_ALPHA_ENABLED;
|
||||
unsigned char *_data;
|
||||
ssize_t _dataLen;
|
||||
int _width;
|
||||
int _height;
|
||||
Format _fileType;
|
||||
PixelFormat _renderFormat;
|
||||
MipmapInfo _mipmaps[MIPMAP_MAX]; // pointer to mipmap images
|
||||
int _numberOfMipmaps;
|
||||
// false if we can't auto detect the image is premultiplied or not.
|
||||
bool _hasPremultipliedAlpha;
|
||||
std::string _filePath;
|
||||
|
||||
protected:
|
||||
// noncopyable
|
||||
Image(const Image&) = delete;
|
||||
Image& operator=(const Image&) = delete;
|
||||
|
||||
// nonmoveable
|
||||
Image(Image&&) = delete;
|
||||
Image& operator=(Image&&) = delete;
|
||||
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
virtual ~Image();
|
||||
|
||||
Format detectFormat(const unsigned char * data, ssize_t dataLen);
|
||||
bool isPng(const unsigned char * data, ssize_t dataLen);
|
||||
bool isJpg(const unsigned char * data, ssize_t dataLen);
|
||||
bool isTiff(const unsigned char * data, ssize_t dataLen);
|
||||
bool isWebp(const unsigned char * data, ssize_t dataLen);
|
||||
bool isPvr(const unsigned char * data, ssize_t dataLen);
|
||||
bool isEtc(const unsigned char * data, ssize_t dataLen);
|
||||
bool isEtc2(const unsigned char * data, ssize_t dataLen);
|
||||
bool isS3TC(const unsigned char * data,ssize_t dataLen);
|
||||
};
|
||||
|
||||
// end of platform group
|
||||
/// @}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
/// @endcond
|
||||
#endif // __CC_IMAGE_H__
|
||||
154
cocos2d-x/cocos/platform/CCPlatformConfig.h
Normal file
154
cocos2d-x/cocos/platform/CCPlatformConfig.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __BASE_CC_PLATFORM_CONFIG_H__
|
||||
#define __BASE_CC_PLATFORM_CONFIG_H__
|
||||
/// @cond DO_NOT_SHOW
|
||||
|
||||
/**
|
||||
Config of cocos2d-x project, per target platform.
|
||||
|
||||
THIS FILE MUST NOT INCLUDE ANY OTHER FILE
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// pre configure
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// define supported target platform macro which CC uses.
|
||||
#define CC_PLATFORM_UNKNOWN 0
|
||||
#define CC_PLATFORM_IOS 1
|
||||
#define CC_PLATFORM_ANDROID 2
|
||||
#define CC_PLATFORM_WIN32 3
|
||||
#define CC_PLATFORM_MARMALADE 4
|
||||
#define CC_PLATFORM_LINUX 5
|
||||
#define CC_PLATFORM_BADA 6
|
||||
#define CC_PLATFORM_BLACKBERRY 7
|
||||
#define CC_PLATFORM_MAC 8
|
||||
#define CC_PLATFORM_NACL 9
|
||||
#define CC_PLATFORM_EMSCRIPTEN 10
|
||||
#define CC_PLATFORM_TIZEN 11
|
||||
#define CC_PLATFORM_QT5 12
|
||||
#define CC_PLATFORM_WINRT 13
|
||||
|
||||
// Determine target platform by compile environment macro.
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_UNKNOWN
|
||||
|
||||
// Apple: Mac and iOS
|
||||
#if defined(__APPLE__) && !defined(ANDROID) // exclude android for binding generator.
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_IPHONE // TARGET_OS_IPHONE includes TARGET_OS_IOS TARGET_OS_TV and TARGET_OS_WATCH. see TargetConditionals.h
|
||||
#undef CC_TARGET_PLATFORM
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_IOS
|
||||
#elif TARGET_OS_MAC
|
||||
#undef CC_TARGET_PLATFORM
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_MAC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// android
|
||||
#if defined(ANDROID)
|
||||
#undef CC_TARGET_PLATFORM
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_ANDROID
|
||||
#endif
|
||||
|
||||
// win32
|
||||
#if defined(_WIN32) && defined(_WINDOWS)
|
||||
#undef CC_TARGET_PLATFORM
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_WIN32
|
||||
#endif
|
||||
|
||||
// linux
|
||||
#if defined(LINUX) && !defined(__APPLE__)
|
||||
#undef CC_TARGET_PLATFORM
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_LINUX
|
||||
#endif
|
||||
|
||||
// marmalade
|
||||
#if defined(MARMALADE)
|
||||
#undef CC_TARGET_PLATFORM
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_MARMALADE
|
||||
#endif
|
||||
|
||||
// bada
|
||||
#if defined(SHP)
|
||||
#undef CC_TARGET_PLATFORM
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_BADA
|
||||
#endif
|
||||
|
||||
// qnx
|
||||
#if defined(__QNX__)
|
||||
#undef CC_TARGET_PLATFORM
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_BLACKBERRY
|
||||
#endif
|
||||
|
||||
// native client
|
||||
#if defined(__native_client__)
|
||||
#undef CC_TARGET_PLATFORM
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_NACL
|
||||
#endif
|
||||
|
||||
// Emscripten
|
||||
#if defined(EMSCRIPTEN)
|
||||
#undef CC_TARGET_PLATFORM
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_EMSCRIPTEN
|
||||
#endif
|
||||
|
||||
// tizen
|
||||
#if defined(TIZEN)
|
||||
#undef CC_TARGET_PLATFORM
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_TIZEN
|
||||
#endif
|
||||
|
||||
// qt5
|
||||
#if defined(CC_TARGET_QT5)
|
||||
#undef CC_TARGET_PLATFORM
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_QT5
|
||||
#endif
|
||||
|
||||
// WinRT (Windows 8.1 Store/Phone App)
|
||||
#if defined(WINRT)
|
||||
#undef CC_TARGET_PLATFORM
|
||||
#define CC_TARGET_PLATFORM CC_PLATFORM_WINRT
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// post configure
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// check user set platform
|
||||
#if ! CC_TARGET_PLATFORM
|
||||
#error "Cannot recognize the target platform; are you targeting an unsupported platform?"
|
||||
#endif
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
||||
#ifndef __MINGW32__
|
||||
#pragma warning (disable:4127)
|
||||
#endif
|
||||
#endif // CC_PLATFORM_WIN32
|
||||
|
||||
/// @endcond
|
||||
#endif // __BASE_CC_PLATFORM_CONFIG_H__
|
||||
48
cocos2d-x/cocos/platform/CCPlatformDefine.h
Normal file
48
cocos2d-x/cocos/platform/CCPlatformDefine.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __PLATFORM_CCPLATFORMDEFINE_H__
|
||||
#define __PLATFORM_CCPLATFORMDEFINE_H__
|
||||
/// @cond DO_NOT_SHOW
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
#include "platform/mac/CCPlatformDefine-mac.h"
|
||||
#elif CC_TARGET_PLATFORM == CC_PLATFORM_IOS
|
||||
#include "platform/ios/CCPlatformDefine-ios.h"
|
||||
#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||
#include "platform/android/CCPlatformDefine-android.h"
|
||||
#elif CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
#include "platform/win32/CCPlatformDefine-win32.h"
|
||||
#elif CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
|
||||
#include "platform/winrt/CCPlatformDefine-winrt.h"
|
||||
#elif CC_TARGET_PLATFORM == CC_PLATFORM_LINUX
|
||||
#include "platform/linux/CCPlatformDefine-linux.h"
|
||||
#endif
|
||||
|
||||
/// @endcond
|
||||
#endif /* __PLATFORM_CCPLATFORMDEFINE_H__*/
|
||||
149
cocos2d-x/cocos/platform/CCSAXParser.cpp
Normal file
149
cocos2d-x/cocos/platform/CCSAXParser.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010 Максим Аксенов
|
||||
Copyright (c) 2010 cocos2d-x.org
|
||||
Copyright (c) 2013 Martell Malone
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "platform/CCSAXParser.h"
|
||||
|
||||
#include <vector> // because its based on windows 8 build :P
|
||||
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include "tinyxml2/tinyxml2.h"
|
||||
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
class XmlSaxHander : public tinyxml2::XMLVisitor
|
||||
{
|
||||
public:
|
||||
XmlSaxHander():_ccsaxParserImp(0){};
|
||||
|
||||
virtual bool VisitEnter( const tinyxml2::XMLElement& element, const tinyxml2::XMLAttribute* firstAttribute );
|
||||
virtual bool VisitExit( const tinyxml2::XMLElement& element );
|
||||
virtual bool Visit( const tinyxml2::XMLText& text );
|
||||
virtual bool Visit( const tinyxml2::XMLUnknown&){ return true; }
|
||||
|
||||
void setSAXParserImp(SAXParser* parser)
|
||||
{
|
||||
_ccsaxParserImp = parser;
|
||||
}
|
||||
|
||||
private:
|
||||
SAXParser *_ccsaxParserImp;
|
||||
};
|
||||
|
||||
|
||||
bool XmlSaxHander::VisitEnter( const tinyxml2::XMLElement& element, const tinyxml2::XMLAttribute* firstAttribute )
|
||||
{
|
||||
//log(" VisitEnter %s",element.Value());
|
||||
|
||||
std::vector<const char*> attsVector;
|
||||
for( const tinyxml2::XMLAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
|
||||
{
|
||||
//log("%s", attrib->Name());
|
||||
attsVector.push_back(attrib->Name());
|
||||
//log("%s",attrib->Value());
|
||||
attsVector.push_back(attrib->Value());
|
||||
}
|
||||
|
||||
// nullptr is used in c++11
|
||||
//attsVector.push_back(nullptr);
|
||||
attsVector.push_back(nullptr);
|
||||
|
||||
SAXParser::startElement(_ccsaxParserImp, (const CC_XML_CHAR *)element.Value(), (const CC_XML_CHAR **)(&attsVector[0]));
|
||||
return true;
|
||||
}
|
||||
bool XmlSaxHander::VisitExit( const tinyxml2::XMLElement& element )
|
||||
{
|
||||
//log("VisitExit %s",element.Value());
|
||||
|
||||
SAXParser::endElement(_ccsaxParserImp, (const CC_XML_CHAR *)element.Value());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XmlSaxHander::Visit( const tinyxml2::XMLText& text )
|
||||
{
|
||||
//log("Visit %s",text.Value());
|
||||
SAXParser::textHandler(_ccsaxParserImp, (const CC_XML_CHAR *)text.Value(), static_cast<int>(strlen(text.Value())));
|
||||
return true;
|
||||
}
|
||||
|
||||
SAXParser::SAXParser()
|
||||
{
|
||||
_delegator = nullptr;
|
||||
}
|
||||
|
||||
SAXParser::~SAXParser(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool SAXParser::init(const char *encoding)
|
||||
{
|
||||
CC_UNUSED_PARAM(encoding);
|
||||
// nothing to do
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SAXParser::parse(const char* xmlData, size_t dataLength)
|
||||
{
|
||||
tinyxml2::XMLDocument tinyDoc;
|
||||
tinyDoc.Parse(xmlData, dataLength);
|
||||
XmlSaxHander printer;
|
||||
printer.setSAXParserImp(this);
|
||||
|
||||
return tinyDoc.Accept( &printer );
|
||||
}
|
||||
|
||||
bool SAXParser::parse(const std::string& filename)
|
||||
{
|
||||
bool ret = false;
|
||||
Data data = FileUtils::getInstance()->getDataFromFile(filename);
|
||||
if (!data.isNull())
|
||||
{
|
||||
ret = parse((const char*)data.getBytes(), data.getSize());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SAXParser::startElement(void *ctx, const CC_XML_CHAR *name, const CC_XML_CHAR **atts)
|
||||
{
|
||||
((SAXParser*)(ctx))->_delegator->startElement(ctx, (char*)name, (const char**)atts);
|
||||
}
|
||||
|
||||
void SAXParser::endElement(void *ctx, const CC_XML_CHAR *name)
|
||||
{
|
||||
((SAXParser*)(ctx))->_delegator->endElement(ctx, (char*)name);
|
||||
}
|
||||
void SAXParser::textHandler(void *ctx, const CC_XML_CHAR *name, int len)
|
||||
{
|
||||
((SAXParser*)(ctx))->_delegator->textHandler(ctx, (char*)name, len);
|
||||
}
|
||||
void SAXParser::setDelegator(SAXDelegator* delegator)
|
||||
{
|
||||
_delegator = delegator;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
122
cocos2d-x/cocos/platform/CCSAXParser.h
Normal file
122
cocos2d-x/cocos/platform/CCSAXParser.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010 cocos2d-x.org
|
||||
Copyright (c) 2010 Максим Аксенов
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __CCSAXPARSER_H__
|
||||
#define __CCSAXPARSER_H__
|
||||
/// @cond DO_NOT_SHOW
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#include "base/ccMacros.h"
|
||||
#include <string>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
/**
|
||||
* @addtogroup platform
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef unsigned char CC_XML_CHAR;
|
||||
|
||||
class CC_DLL SAXDelegator
|
||||
{
|
||||
public:
|
||||
virtual ~SAXDelegator() {}
|
||||
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
virtual void startElement(void *ctx, const char *name, const char **atts) = 0;
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
virtual void endElement(void *ctx, const char *name) = 0;
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
virtual void textHandler(void *ctx, const char *s, int len) = 0;
|
||||
};
|
||||
|
||||
class CC_DLL SAXParser
|
||||
{
|
||||
SAXDelegator* _delegator;
|
||||
public:
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
SAXParser();
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
~SAXParser(void);
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
bool init(const char *encoding);
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
bool parse(const char* xmlData, size_t dataLength);
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
bool parse(const std::string& filename);
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
void setDelegator(SAXDelegator* delegator);
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
static void startElement(void *ctx, const CC_XML_CHAR *name, const CC_XML_CHAR **atts);
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
static void endElement(void *ctx, const CC_XML_CHAR *name);
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
static void textHandler(void *ctx, const CC_XML_CHAR *name, int len);
|
||||
};
|
||||
|
||||
// end of platform group
|
||||
/// @}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
/// @endcond
|
||||
#endif //__CCSAXPARSER_H__
|
||||
83
cocos2d-x/cocos/platform/CCStdC.h
Normal file
83
cocos2d-x/cocos/platform/CCStdC.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
#if _MSC_VER < 1800
|
||||
#if !defined(isnan)
|
||||
#define isnan _isnan
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#if _MSC_VER >= 1600
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include "platform/win32/compat/stdint.h"
|
||||
#endif
|
||||
|
||||
// Conflicted with ParticleSystem::PositionType::RELATIVE, so we need to undef it.
|
||||
#ifdef RELATIVE
|
||||
#undef RELATIVE
|
||||
#endif
|
||||
|
||||
// Conflicted with CCBReader::SizeType::RELATIVE and CCBReader::ScaleType::RELATIVE, so we need to undef it.
|
||||
#ifdef ABSOLUTE
|
||||
#undef ABSOLUTE
|
||||
#endif
|
||||
|
||||
// Conflicted with HttpRequest::Type::DELETE, so we need to undef it.
|
||||
#ifdef DELETE
|
||||
#undef DELETE
|
||||
#endif
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
#else
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
31
cocos2d-x/cocos/platform/android/Android.mk
Normal file
31
cocos2d-x/cocos/platform/android/Android.mk
Normal file
@@ -0,0 +1,31 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := cocos2dxandroid_static
|
||||
|
||||
LOCAL_MODULE_FILENAME := libcocos2dandroid
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
CCDevice-android.cpp \
|
||||
CCFileUtils-android.cpp \
|
||||
CCApplication-android.cpp \
|
||||
CCCanvasRenderingContext2D-android.cpp \
|
||||
jni/JniImp.cpp \
|
||||
jni/JniHelper.cpp \
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH) \
|
||||
$(LOCAL_PATH)/.. \
|
||||
$(LOCAL_PATH)/../.. \
|
||||
$(LOCAL_PATH)/../../..
|
||||
|
||||
LOCAL_EXPORT_LDLIBS := -lGLESv2 \
|
||||
-lEGL \
|
||||
-llog \
|
||||
-landroid
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := v8_static
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
307
cocos2d-x/cocos/platform/android/CCApplication-android.cpp
Normal file
307
cocos2d-x/cocos/platform/android/CCApplication-android.cpp
Normal file
@@ -0,0 +1,307 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "platform/CCApplication.h"
|
||||
#include <EGL/egl.h>
|
||||
#include <cstring>
|
||||
#include <jni.h>
|
||||
#include "platform/android/jni/JniImp.h"
|
||||
#include "platform/android/CCGL-android.h"
|
||||
#include "base/CCScheduler.h"
|
||||
#include "base/CCConfiguration.h"
|
||||
#include "audio/include/AudioEngine.h"
|
||||
#include "scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "scripting/js-bindings/event/EventDispatcher.h"
|
||||
|
||||
#define LOG_APP_TAG "CCApplication_android Debug"
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_APP_TAG,__VA_ARGS__)
|
||||
|
||||
// IDEA: using ndk-r10c will cause the next function could not be found. It may be a bug of ndk-r10c.
|
||||
// Here is the workaround method to fix the problem.
|
||||
#ifdef __aarch64__
|
||||
extern "C" size_t __ctype_get_mb_cur_max(void)
|
||||
{
|
||||
return (size_t) sizeof(wchar_t);
|
||||
}
|
||||
#endif
|
||||
|
||||
PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOESEXT = 0;
|
||||
PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOESEXT = 0;
|
||||
PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOESEXT = 0;
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
void Application::updateViewSize(int width, int height)
|
||||
{
|
||||
_viewSize.x = width;
|
||||
_viewSize.y = height;
|
||||
|
||||
// handle resize event
|
||||
Application::getInstance()->getScheduler()->performFunctionInCocosThread([=]() {
|
||||
EventDispatcher::dispatchResizeEvent(width, height);
|
||||
});
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void Java_org_cocos2dx_lib_Cocos2dxGLSurfaceView_nativeOnSizeChanged(JNIEnv * env, jobject obj, jint width, jint height) {
|
||||
auto inst = Application::getInstance();
|
||||
// nativeOnSizeChanged is firstly called before Application initiating.
|
||||
if (inst != nullptr) {
|
||||
inst->updateViewSize(width, height);
|
||||
}
|
||||
}
|
||||
void Java_org_cocos2dx_lib_Cocos2dxOrientationHelper_nativeOnOrientationChanged(JNIEnv * env, jobject obj, jint rotation) {
|
||||
auto inst = Application::getInstance();
|
||||
// nativeOnSizeChanged is firstly called before Application initiating.
|
||||
if (inst != nullptr) {
|
||||
// handle orientation change event
|
||||
inst->getScheduler()->performFunctionInCocosThread([=]() {
|
||||
EventDispatcher::dispatchOrientationChangeEvent(rotation);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Application* Application::_instance = nullptr;
|
||||
std::shared_ptr<Scheduler> Application::_scheduler = nullptr;
|
||||
|
||||
Application::Application(const std::string& name, int width, int height)
|
||||
{
|
||||
Application::_instance = this;
|
||||
Configuration::getInstance();
|
||||
|
||||
_scheduler = std::make_shared<Scheduler>();
|
||||
|
||||
PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOESEXT = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES");
|
||||
PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOESEXT = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES");
|
||||
PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOESEXT = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES");
|
||||
|
||||
_renderTexture = new RenderTexture(width, height);
|
||||
updateViewSize(width, height);
|
||||
}
|
||||
|
||||
Application::~Application()
|
||||
{
|
||||
#if USE_AUDIO
|
||||
AudioEngine::end();
|
||||
#endif
|
||||
|
||||
EventDispatcher::destroy();
|
||||
se::ScriptEngine::destroyInstance();
|
||||
|
||||
delete _renderTexture;
|
||||
_renderTexture = nullptr;
|
||||
|
||||
Application::_instance = nullptr;
|
||||
}
|
||||
|
||||
void Application::start()
|
||||
{
|
||||
if(!applicationDidFinishLaunching())
|
||||
return;
|
||||
}
|
||||
|
||||
void Application::restart()
|
||||
{
|
||||
restartJSVM();
|
||||
}
|
||||
|
||||
void Application::end()
|
||||
{
|
||||
exitApplication();
|
||||
}
|
||||
|
||||
void Application::setMultitouch(bool /*value*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Application::applicationDidFinishLaunching()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::onPause()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Application::onResume()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Application::setPreferredFramesPerSecond(int fps)
|
||||
{
|
||||
_fps = fps;
|
||||
setPreferredFramesPerSecondJNI(_fps);
|
||||
}
|
||||
|
||||
std::string Application::getCurrentLanguageCode() const
|
||||
{
|
||||
return getCurrentLanguageCodeJNI();
|
||||
}
|
||||
|
||||
bool Application::isDisplayStats() {
|
||||
se::AutoHandleScope hs;
|
||||
se::Value ret;
|
||||
char commandBuf[100] = "cc.debug.isDisplayStats();";
|
||||
se::ScriptEngine::getInstance()->evalString(commandBuf, 100, &ret);
|
||||
return ret.toBoolean();
|
||||
}
|
||||
|
||||
void Application::setDisplayStats(bool isShow) {
|
||||
se::AutoHandleScope hs;
|
||||
char commandBuf[100] = {0};
|
||||
sprintf(commandBuf, "cc.debug.setDisplayStats(%s);", isShow ? "true" : "false");
|
||||
se::ScriptEngine::getInstance()->evalString(commandBuf);
|
||||
}
|
||||
|
||||
Application::LanguageType Application::getCurrentLanguage() const
|
||||
{
|
||||
std::string languageName = getCurrentLanguageJNI();
|
||||
const char* pLanguageName = languageName.c_str();
|
||||
LanguageType ret = LanguageType::ENGLISH;
|
||||
|
||||
if (0 == strcmp("zh", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::CHINESE;
|
||||
}
|
||||
else if (0 == strcmp("en", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::ENGLISH;
|
||||
}
|
||||
else if (0 == strcmp("fr", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::FRENCH;
|
||||
}
|
||||
else if (0 == strcmp("it", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::ITALIAN;
|
||||
}
|
||||
else if (0 == strcmp("de", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::GERMAN;
|
||||
}
|
||||
else if (0 == strcmp("es", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::SPANISH;
|
||||
}
|
||||
else if (0 == strcmp("ru", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::RUSSIAN;
|
||||
}
|
||||
else if (0 == strcmp("nl", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::DUTCH;
|
||||
}
|
||||
else if (0 == strcmp("ko", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::KOREAN;
|
||||
}
|
||||
else if (0 == strcmp("ja", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::JAPANESE;
|
||||
}
|
||||
else if (0 == strcmp("hu", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::HUNGARIAN;
|
||||
}
|
||||
else if (0 == strcmp("pt", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::PORTUGUESE;
|
||||
}
|
||||
else if (0 == strcmp("ar", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::ARABIC;
|
||||
}
|
||||
else if (0 == strcmp("nb", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::NORWEGIAN;
|
||||
}
|
||||
else if (0 == strcmp("pl", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::POLISH;
|
||||
}
|
||||
else if (0 == strcmp("tr", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::TURKISH;
|
||||
}
|
||||
else if (0 == strcmp("uk", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::UKRAINIAN;
|
||||
}
|
||||
else if (0 == strcmp("ro", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::ROMANIAN;
|
||||
}
|
||||
else if (0 == strcmp("bg", pLanguageName))
|
||||
{
|
||||
ret = LanguageType::BULGARIAN;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Application::Platform Application::getPlatform() const
|
||||
{
|
||||
return Platform::ANDROIDOS;
|
||||
}
|
||||
|
||||
float Application::getScreenScale() const
|
||||
{
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
GLint Application::getMainFBO() const
|
||||
{
|
||||
return _mainFBO;
|
||||
}
|
||||
|
||||
void Application::onCreateView(PixelFormat& /*pixelformat*/, DepthFormat& /*depthFormat*/, int& /*multisamplingCount*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Application::openURL(const std::string &url)
|
||||
{
|
||||
return openURLJNI(url);
|
||||
}
|
||||
|
||||
void Application::copyTextToClipboard(const std::string &text)
|
||||
{
|
||||
copyTextToClipboardJNI(text);
|
||||
}
|
||||
|
||||
std::string Application::getSystemVersion()
|
||||
{
|
||||
return getSystemVersionJNI();
|
||||
}
|
||||
|
||||
const cocos2d::Vec2& Application::getViewSize() const
|
||||
{
|
||||
return _viewSize;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
@@ -0,0 +1,619 @@
|
||||
#include "platform/CCCanvasRenderingContext2D.h"
|
||||
#include "base/ccTypes.h"
|
||||
#include "base/csscolorparser.hpp"
|
||||
|
||||
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "platform/android/jni/JniHelper.h"
|
||||
#include "platform/android/jni/JniImp.h"
|
||||
|
||||
#include <regex>
|
||||
|
||||
#ifndef JCLS_CANVASIMPL
|
||||
#define JCLS_CANVASIMPL "org/cocos2dx/lib/CanvasRenderingContext2DImpl"
|
||||
#endif
|
||||
|
||||
using namespace cocos2d;
|
||||
|
||||
enum class CanvasTextAlign {
|
||||
LEFT,
|
||||
CENTER,
|
||||
RIGHT
|
||||
};
|
||||
|
||||
enum class CanvasTextBaseline {
|
||||
TOP,
|
||||
MIDDLE,
|
||||
BOTTOM
|
||||
};
|
||||
|
||||
class CanvasRenderingContext2DImpl
|
||||
{
|
||||
public:
|
||||
CanvasRenderingContext2DImpl()
|
||||
{
|
||||
jobject obj = JniHelper::newObject(JCLS_CANVASIMPL);
|
||||
_obj = JniHelper::getEnv()->NewGlobalRef(obj);
|
||||
JniHelper::getEnv()->DeleteLocalRef(obj);
|
||||
}
|
||||
|
||||
~CanvasRenderingContext2DImpl()
|
||||
{
|
||||
JniHelper::getEnv()->DeleteGlobalRef(_obj);
|
||||
}
|
||||
|
||||
void recreateBuffer(float w, float h)
|
||||
{
|
||||
_bufferWidth = w;
|
||||
_bufferHeight = h;
|
||||
if (_bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "recreateBuffer", w, h);
|
||||
fillData();
|
||||
}
|
||||
|
||||
void beginPath()
|
||||
{
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "beginPath");
|
||||
}
|
||||
|
||||
void closePath()
|
||||
{
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "closePath");
|
||||
}
|
||||
|
||||
void moveTo(float x, float y)
|
||||
{
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "moveTo", x, y);
|
||||
}
|
||||
|
||||
void lineTo(float x, float y)
|
||||
{
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "lineTo", x, y);
|
||||
}
|
||||
|
||||
void stroke()
|
||||
{
|
||||
if (_bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "stroke");
|
||||
fillData();
|
||||
}
|
||||
|
||||
void fill()
|
||||
{
|
||||
if (_bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "fill");
|
||||
fillData();
|
||||
}
|
||||
|
||||
void saveContext()
|
||||
{
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "saveContext");
|
||||
}
|
||||
|
||||
void restoreContext()
|
||||
{
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "restoreContext");
|
||||
}
|
||||
|
||||
void rect(float x, float y, float w, float h)
|
||||
{
|
||||
if (_bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "rect", x, y, w, h);
|
||||
fillData();
|
||||
}
|
||||
|
||||
void clearRect(float x, float y, float w, float h)
|
||||
{
|
||||
if (_bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
if (x >= _bufferWidth || y >= _bufferHeight)
|
||||
return;
|
||||
if (x + w > _bufferWidth)
|
||||
w = _bufferWidth - x;
|
||||
if (y + h > _bufferHeight)
|
||||
h = _bufferHeight - y;
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "clearRect", x, y, w, h);
|
||||
fillData();
|
||||
}
|
||||
|
||||
void fillRect(float x, float y, float w, float h)
|
||||
{
|
||||
if (_bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
if (x >= _bufferWidth || y >= _bufferHeight)
|
||||
return;
|
||||
if (x + w > _bufferWidth)
|
||||
w = _bufferWidth - x;
|
||||
if (y + h > _bufferHeight)
|
||||
h = _bufferHeight - y;
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "fillRect", x, y, w, h);
|
||||
fillData();
|
||||
}
|
||||
|
||||
void fillText(const std::string& text, float x, float y, float maxWidth)
|
||||
{
|
||||
if (text.empty() || _bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "fillText", text, x, y, maxWidth);
|
||||
fillData();
|
||||
}
|
||||
|
||||
void strokeText(const std::string& text, float x, float y, float maxWidth)
|
||||
{
|
||||
if (text.empty() || _bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "strokeText", text, x, y, maxWidth);
|
||||
fillData();
|
||||
}
|
||||
|
||||
float measureText(const std::string& text)
|
||||
{
|
||||
if (text.empty())
|
||||
return 0.0f;
|
||||
return JniHelper::callObjectFloatMethod(_obj, JCLS_CANVASIMPL, "measureText", text);
|
||||
}
|
||||
|
||||
void updateFont(const std::string& fontName, float fontSize, bool bold, bool italic, bool oblique, bool smallCaps)
|
||||
{
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "updateFont", fontName, fontSize, bold, italic, oblique, smallCaps);
|
||||
}
|
||||
|
||||
void setLineCap(const std::string& lineCap) {
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "setLineCap", lineCap);
|
||||
}
|
||||
|
||||
void setLineJoin(const std::string& lineJoin) {
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "setLineJoin", lineJoin);
|
||||
}
|
||||
|
||||
void setTextAlign(CanvasTextAlign align)
|
||||
{
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "setTextAlign", (int)align);
|
||||
}
|
||||
|
||||
void setTextBaseline(CanvasTextBaseline baseline)
|
||||
{
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "setTextBaseline", (int)baseline);
|
||||
}
|
||||
|
||||
void setFillStyle(float r, float g, float b, float a)
|
||||
{
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "setFillStyle", r, g, b, a);
|
||||
}
|
||||
|
||||
void setStrokeStyle(float r, float g, float b, float a)
|
||||
{
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "setStrokeStyle", r, g, b, a);
|
||||
}
|
||||
|
||||
void setLineWidth(float lineWidth)
|
||||
{
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "setLineWidth", lineWidth);
|
||||
}
|
||||
|
||||
void _fillImageData(const Data &imageData, float imageWidth, float imageHeight, float offsetX, float offsetY) {
|
||||
if (_bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
|
||||
jbyteArray arr = JniHelper::getEnv()->NewByteArray(imageData.getSize());
|
||||
JniHelper::getEnv()->SetByteArrayRegion(arr, 0, imageData.getSize(),
|
||||
(const jbyte *) imageData.getBytes());
|
||||
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "_fillImageData", arr, imageWidth,
|
||||
imageHeight, offsetX, offsetY);
|
||||
JniHelper::getEnv()->DeleteLocalRef(arr);
|
||||
|
||||
fillData();
|
||||
}
|
||||
|
||||
const Data& getDataRef() const
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
void setPremultiply(bool multiply)
|
||||
{
|
||||
_premultiply = multiply;
|
||||
}
|
||||
|
||||
#define CLAMP(V, HI) std::min( (V), (HI) )
|
||||
void unMultiplyAlpha(unsigned char* ptr, ssize_t size)
|
||||
{
|
||||
// Android source data is not premultiplied alpha when API >= 19
|
||||
// please refer CanvasRenderingContext2DImpl::recreateBuffer(float w, float h)
|
||||
// in CanvasRenderingContext2DImpl.java
|
||||
// if (getAndroidSDKInt() >= 19)
|
||||
// return;
|
||||
|
||||
float alpha;
|
||||
for (int i = 0; i < size; i += 4)
|
||||
{
|
||||
alpha = (float)ptr[i + 3];
|
||||
if (alpha > 0)
|
||||
{
|
||||
ptr[i] = CLAMP((int)((float)ptr[i] / alpha * 255), 255);
|
||||
ptr[i+1] = CLAMP((int)((float)ptr[i+1] / alpha * 255), 255);
|
||||
ptr[i+2] = CLAMP((int)((float)ptr[i+2] / alpha * 255), 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fillData()
|
||||
{
|
||||
jbyteArray arr = JniHelper::callObjectByteArrayMethod(_obj, JCLS_CANVASIMPL, "getDataRef");
|
||||
jsize len = JniHelper::getEnv()->GetArrayLength(arr);
|
||||
jbyte* jbarray = (jbyte *)malloc(len * sizeof(jbyte));
|
||||
JniHelper::getEnv()->GetByteArrayRegion(arr,0,len,jbarray);
|
||||
if (!_premultiply)
|
||||
{
|
||||
unMultiplyAlpha( (unsigned char*) jbarray, len);
|
||||
}
|
||||
_data.fastSet((unsigned char*) jbarray, len); //IDEA: DON'T create new jbarray every time.
|
||||
JniHelper::getEnv()->DeleteLocalRef(arr);
|
||||
}
|
||||
|
||||
private:
|
||||
jobject _obj = nullptr;
|
||||
Data _data;
|
||||
float _bufferWidth = 0.0f;
|
||||
float _bufferHeight = 0.0f;
|
||||
bool _premultiply = true;
|
||||
};
|
||||
|
||||
namespace {
|
||||
void fillRectWithColor(uint8_t* buf, uint32_t totalWidth, uint32_t totalHeight, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
assert(x + width <= totalWidth);
|
||||
assert(y + height <= totalHeight);
|
||||
|
||||
uint32_t y0 = totalHeight - (y + height);
|
||||
uint32_t y1 = totalHeight - y;
|
||||
uint8_t* p;
|
||||
for (uint32_t offsetY = y0; offsetY < y1; ++offsetY)
|
||||
{
|
||||
for (uint32_t offsetX = x; offsetX < (x + width); ++offsetX)
|
||||
{
|
||||
p = buf + (totalWidth * offsetY + offsetX) * 3;
|
||||
*p++ = r;
|
||||
*p++ = g;
|
||||
*p++ = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
CanvasGradient::CanvasGradient()
|
||||
{
|
||||
// SE_LOGD("CanvasGradient constructor: %p\n", this);
|
||||
}
|
||||
|
||||
CanvasGradient::~CanvasGradient()
|
||||
{
|
||||
// SE_LOGD("CanvasGradient destructor: %p\n", this);
|
||||
}
|
||||
|
||||
void CanvasGradient::addColorStop(float offset, const std::string& color)
|
||||
{
|
||||
// SE_LOGD("CanvasGradient::addColorStop: %p\n", this);
|
||||
}
|
||||
|
||||
// CanvasRenderingContext2D
|
||||
|
||||
CanvasRenderingContext2D::CanvasRenderingContext2D(float width, float height)
|
||||
: __width(width)
|
||||
, __height(height)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D constructor: %p, width: %f, height: %f\n", this, width, height);
|
||||
_impl = new CanvasRenderingContext2DImpl();
|
||||
recreateBufferIfNeeded();
|
||||
}
|
||||
|
||||
CanvasRenderingContext2D::~CanvasRenderingContext2D()
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D destructor: %p\n", this);
|
||||
delete _impl;
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::recreateBufferIfNeeded()
|
||||
{
|
||||
if (_isBufferSizeDirty)
|
||||
{
|
||||
_isBufferSizeDirty = false;
|
||||
// SE_LOGD("Recreate buffer %p, w: %f, h:%f\n", this, __width, __height);
|
||||
_impl->recreateBuffer(__width, __height);
|
||||
if (_canvasBufferUpdatedCB != nullptr)
|
||||
_canvasBufferUpdatedCB(_impl->getDataRef());
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::rect(float x, float y, float width, float height)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D::rect: %p, %f, %f, %f, %f\n", this, x, y, width, height);
|
||||
recreateBufferIfNeeded();
|
||||
_impl->rect(x, y, width, height);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D::clearRect: %p, %f, %f, %f, %f\n", this, x, y, width, height);
|
||||
recreateBufferIfNeeded();
|
||||
_impl->clearRect(x, y, width, height);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::fillRect(float x, float y, float width, float height)
|
||||
{
|
||||
recreateBufferIfNeeded();
|
||||
_impl->fillRect(x, y, width, height);
|
||||
|
||||
if (_canvasBufferUpdatedCB != nullptr)
|
||||
_canvasBufferUpdatedCB(_impl->getDataRef());
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::fillText(const std::string& text, float x, float y, float maxWidth)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D::fillText: %s, %f, %f, %f\n", text.c_str(), x, y, maxWidth);
|
||||
if (text.empty())
|
||||
return;
|
||||
recreateBufferIfNeeded();
|
||||
|
||||
_impl->fillText(text, x, y, maxWidth);
|
||||
if (_canvasBufferUpdatedCB != nullptr)
|
||||
_canvasBufferUpdatedCB(_impl->getDataRef());
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::strokeText(const std::string& text, float x, float y, float maxWidth)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D::strokeText: %s, %f, %f, %f\n", text.c_str(), x, y, maxWidth);
|
||||
if (text.empty())
|
||||
return;
|
||||
recreateBufferIfNeeded();
|
||||
|
||||
_impl->strokeText(text, x, y, maxWidth);
|
||||
|
||||
if (_canvasBufferUpdatedCB != nullptr)
|
||||
_canvasBufferUpdatedCB(_impl->getDataRef());
|
||||
}
|
||||
|
||||
cocos2d::Size CanvasRenderingContext2D::measureText(const std::string& text)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D::measureText: %s\n", text.c_str());
|
||||
return cocos2d::Size(_impl->measureText(text), 0);
|
||||
}
|
||||
|
||||
CanvasGradient* CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::save()
|
||||
{
|
||||
_impl->saveContext();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::beginPath()
|
||||
{
|
||||
_impl->beginPath();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::closePath()
|
||||
{
|
||||
_impl->closePath();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::moveTo(float x, float y)
|
||||
{
|
||||
_impl->moveTo(x, y);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::lineTo(float x, float y)
|
||||
{
|
||||
_impl->lineTo(x, y);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::stroke()
|
||||
{
|
||||
_impl->stroke();
|
||||
|
||||
if (_canvasBufferUpdatedCB != nullptr)
|
||||
_canvasBufferUpdatedCB(_impl->getDataRef());
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::fill()
|
||||
{
|
||||
_impl->fill();
|
||||
|
||||
if (_canvasBufferUpdatedCB != nullptr)
|
||||
_canvasBufferUpdatedCB(_impl->getDataRef());
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::restore()
|
||||
{
|
||||
_impl->restoreContext();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::setCanvasBufferUpdatedCallback(const CanvasBufferUpdatedCallback& cb)
|
||||
{
|
||||
_canvasBufferUpdatedCB = cb;
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::setPremultiply(bool multiply)
|
||||
{
|
||||
_impl->setPremultiply(multiply);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set__width(float width)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D::set__width: %f\n", width);
|
||||
__width = width;
|
||||
_isBufferSizeDirty = true;
|
||||
recreateBufferIfNeeded();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set__height(float height)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D::set__height: %f\n", height);
|
||||
__height = height;
|
||||
_isBufferSizeDirty = true;
|
||||
recreateBufferIfNeeded();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_lineWidth(float lineWidth)
|
||||
{
|
||||
_lineWidth = lineWidth;
|
||||
_impl->setLineWidth(lineWidth);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_lineJoin(const std::string& lineJoin)
|
||||
{
|
||||
if(lineJoin.empty()) return ;
|
||||
_impl->setLineJoin(lineJoin);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_lineCap(const std::string& lineCap)
|
||||
{
|
||||
if(lineCap.empty()) return ;
|
||||
_impl->setLineCap(lineCap);
|
||||
}
|
||||
|
||||
/*
|
||||
* support format e.g.: "oblique bold small-caps 18px Arial"
|
||||
* "italic bold small-caps 25px Arial"
|
||||
* "italic 25px Arial"
|
||||
* */
|
||||
void CanvasRenderingContext2D::set_font(const std::string& font)
|
||||
{
|
||||
if (_font != font)
|
||||
{
|
||||
_font = font;
|
||||
std::string fontName = "sans-serif";
|
||||
std::string fontSizeStr = "30";
|
||||
std::regex re("\\s*((\\d+)([\\.]\\d+)?)px\\s+([^\\r\\n]*)");
|
||||
std::match_results<std::string::const_iterator> results;
|
||||
if (std::regex_search(_font.cbegin(), _font.cend(), results, re))
|
||||
{
|
||||
fontSizeStr = results[2].str();
|
||||
// support get font name from `60px American` or `60px "American abc-abc_abc"`
|
||||
// support get font name contain space,example `times new roman`
|
||||
// if regex rule that does not conform to the rules,such as Chinese,it defaults to sans-serif
|
||||
std::match_results<std::string::const_iterator> fontResults;
|
||||
std::regex fontRe("([\\w\\s-]+|\"[\\w\\s-]+\"$)");
|
||||
if(std::regex_match(results[4].str(), fontResults, fontRe))
|
||||
{
|
||||
fontName = results[4].str();
|
||||
}
|
||||
}
|
||||
|
||||
float fontSize = atof(fontSizeStr.c_str());
|
||||
bool isBold = font.find("bold", 0) != std::string::npos;
|
||||
bool isItalic = font.find("italic", 0) != std::string::npos;
|
||||
bool isSmallCaps = font.find("small-caps", 0) != std::string::npos;
|
||||
bool isOblique = font.find("oblique", 0) != std::string::npos;
|
||||
//font-style: italic, oblique, normal
|
||||
//font-weight: normal, bold
|
||||
//font-variant: normal, small-caps
|
||||
_impl->updateFont(fontName, fontSize, isBold, isItalic, isOblique, isSmallCaps);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_textAlign(const std::string& textAlign)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D::set_textAlign: %s\n", textAlign.c_str());
|
||||
if (textAlign == "left")
|
||||
{
|
||||
_impl->setTextAlign(CanvasTextAlign::LEFT);
|
||||
}
|
||||
else if (textAlign == "center" || textAlign == "middle")
|
||||
{
|
||||
_impl->setTextAlign(CanvasTextAlign::CENTER);
|
||||
}
|
||||
else if (textAlign == "right")
|
||||
{
|
||||
_impl->setTextAlign(CanvasTextAlign::RIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_textBaseline(const std::string& textBaseline)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D::set_textBaseline: %s\n", textBaseline.c_str());
|
||||
if (textBaseline == "top")
|
||||
{
|
||||
_impl->setTextBaseline(CanvasTextBaseline::TOP);
|
||||
}
|
||||
else if (textBaseline == "middle")
|
||||
{
|
||||
_impl->setTextBaseline(CanvasTextBaseline::MIDDLE);
|
||||
}
|
||||
else if (textBaseline == "bottom" || textBaseline == "alphabetic") //REFINE:, how to deal with alphabetic, currently we handle it as bottom mode.
|
||||
{
|
||||
_impl->setTextBaseline(CanvasTextBaseline::BOTTOM);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_fillStyle(const std::string& fillStyle)
|
||||
{
|
||||
CSSColorParser::Color color = CSSColorParser::parse(fillStyle);
|
||||
_impl->setFillStyle(color.r/255.0f, color.g/255.0f, color.b/255.0f, color.a);
|
||||
// SE_LOGD("CanvasRenderingContext2D::set_fillStyle: %s, (%d, %d, %d, %f)\n", fillStyle.c_str(), color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_strokeStyle(const std::string& strokeStyle)
|
||||
{
|
||||
CSSColorParser::Color color = CSSColorParser::parse(strokeStyle);
|
||||
_impl->setStrokeStyle(color.r/255.0f, color.g/255.0f, color.b/255.0f, color.a);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_globalCompositeOperation(const std::string& globalCompositeOperation)
|
||||
{
|
||||
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::_fillImageData(const Data& imageData, float imageWidth, float imageHeight, float offsetX, float offsetY)
|
||||
{
|
||||
_impl->_fillImageData(imageData, imageWidth, imageHeight, offsetX, offsetY);
|
||||
if (_canvasBufferUpdatedCB != nullptr)
|
||||
_canvasBufferUpdatedCB(_impl->getDataRef());
|
||||
}
|
||||
// transform
|
||||
//REFINE:
|
||||
|
||||
void CanvasRenderingContext2D::translate(float x, float y)
|
||||
{
|
||||
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::scale(float x, float y)
|
||||
{
|
||||
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::rotate(float angle)
|
||||
{
|
||||
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::transform(float a, float b, float c, float d, float e, float f)
|
||||
{
|
||||
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::setTransform(float a, float b, float c, float d, float e, float f)
|
||||
{
|
||||
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
136
cocos2d-x/cocos/platform/android/CCDevice-android.cpp
Normal file
136
cocos2d-x/cocos/platform/android/CCDevice-android.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||
|
||||
#include "platform/CCDevice.h"
|
||||
#include <string.h>
|
||||
#include <android/log.h>
|
||||
#include <jni.h>
|
||||
#include "base/ccTypes.h"
|
||||
#include "platform/android/jni/JniHelper.h"
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include "base/ccUTF8.h"
|
||||
#include "platform/CCApplication.h"
|
||||
|
||||
#ifndef JCLS_HELPER
|
||||
#define JCLS_HELPER "org/cocos2dx/lib/Cocos2dxHelper"
|
||||
#endif
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
int Device::getDPI()
|
||||
{
|
||||
static int dpi = -1;
|
||||
if (dpi == -1)
|
||||
{
|
||||
dpi = JniHelper::callStaticIntMethod(JCLS_HELPER, "getDPI");
|
||||
}
|
||||
return dpi;
|
||||
}
|
||||
|
||||
void Device::setAccelerometerEnabled(bool isEnabled)
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "enableAccelerometer");
|
||||
}
|
||||
else
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "disableAccelerometer");
|
||||
}
|
||||
}
|
||||
|
||||
void Device::setAccelerometerInterval(float interval)
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "setAccelerometerInterval", interval);
|
||||
}
|
||||
|
||||
const Device::MotionValue& Device::getDeviceMotionValue()
|
||||
{
|
||||
static MotionValue __motionValue;
|
||||
float* v = JniHelper::callStaticFloatArrayMethod(JCLS_HELPER, "getDeviceMotionValue");
|
||||
__motionValue.accelerationX = v[0];
|
||||
__motionValue.accelerationY = v[1];
|
||||
__motionValue.accelerationZ = v[2];
|
||||
|
||||
__motionValue.accelerationIncludingGravityX = v[3];
|
||||
__motionValue.accelerationIncludingGravityY = v[4];
|
||||
__motionValue.accelerationIncludingGravityZ = v[5];
|
||||
|
||||
__motionValue.rotationRateAlpha = v[6];
|
||||
__motionValue.rotationRateBeta = v[7];
|
||||
__motionValue.rotationRateGamma = v[8];
|
||||
|
||||
return __motionValue;
|
||||
}
|
||||
|
||||
Device::Rotation Device::getDeviceRotation()
|
||||
{
|
||||
int rotation = JniHelper::callStaticIntMethod(JCLS_HELPER, "getDeviceRotation");
|
||||
return (Device::Rotation)rotation;
|
||||
}
|
||||
|
||||
std::string Device::getDeviceModel()
|
||||
{
|
||||
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getDeviceModel");
|
||||
}
|
||||
|
||||
void Device::setKeepScreenOn(bool value)
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "setKeepScreenOn", value);
|
||||
}
|
||||
|
||||
void Device::vibrate(float duration)
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "vibrate", duration);
|
||||
}
|
||||
|
||||
float Device::getBatteryLevel()
|
||||
{
|
||||
return JniHelper::callStaticFloatMethod(JCLS_HELPER, "getBatteryLevel");
|
||||
}
|
||||
|
||||
Device::NetworkType Device::getNetworkType()
|
||||
{
|
||||
return (Device::NetworkType)JniHelper::callStaticIntMethod(JCLS_HELPER, "getNetworkType");
|
||||
}
|
||||
|
||||
cocos2d::Vec4 Device::getSafeAreaEdge()
|
||||
{
|
||||
float *data = JniHelper::callStaticFloatArrayMethod(JCLS_HELPER, "getSafeArea");
|
||||
return cocos2d::Vec4(data[0], data[1], data[2],data[3]);
|
||||
}
|
||||
|
||||
int Device::getDevicePixelRatio()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||
333
cocos2d-x/cocos/platform/android/CCFileUtils-android.cpp
Normal file
333
cocos2d-x/cocos/platform/android/CCFileUtils-android.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||
|
||||
#include "platform/android/CCFileUtils-android.h"
|
||||
#include "platform/android/jni/JniHelper.h"
|
||||
#include "platform/android/jni/JniImp.h"
|
||||
#include "android/asset_manager.h"
|
||||
#include "android/asset_manager_jni.h"
|
||||
#include "base/ZipUtils.h"
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define LOG_TAG "CCFileUtils-android.cpp"
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
|
||||
|
||||
#define ASSETS_FOLDER_NAME "@assets/"
|
||||
|
||||
#ifndef JCLS_HELPER
|
||||
#define JCLS_HELPER "org/cocos2dx/lib/Cocos2dxHelper"
|
||||
#endif
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
AAssetManager* FileUtilsAndroid::assetmanager = nullptr;
|
||||
ZipFile* FileUtilsAndroid::obbfile = nullptr;
|
||||
|
||||
void FileUtilsAndroid::setassetmanager(AAssetManager* a) {
|
||||
if (nullptr == a) {
|
||||
LOGD("setassetmanager : received unexpected nullptr parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
cocos2d::FileUtilsAndroid::assetmanager = a;
|
||||
}
|
||||
|
||||
FileUtils* FileUtils::getInstance()
|
||||
{
|
||||
if (s_sharedFileUtils == nullptr)
|
||||
{
|
||||
s_sharedFileUtils = new FileUtilsAndroid();
|
||||
if (!s_sharedFileUtils->init())
|
||||
{
|
||||
delete s_sharedFileUtils;
|
||||
s_sharedFileUtils = nullptr;
|
||||
CCLOG("ERROR: Could not init CCFileUtilsAndroid");
|
||||
}
|
||||
}
|
||||
return s_sharedFileUtils;
|
||||
}
|
||||
|
||||
FileUtilsAndroid::FileUtilsAndroid()
|
||||
{
|
||||
}
|
||||
|
||||
FileUtilsAndroid::~FileUtilsAndroid()
|
||||
{
|
||||
if (obbfile)
|
||||
{
|
||||
delete obbfile;
|
||||
obbfile = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileUtilsAndroid::init()
|
||||
{
|
||||
_defaultResRootPath = ASSETS_FOLDER_NAME;
|
||||
|
||||
std::string assetsPath(getApkPathJNI());
|
||||
if (assetsPath.find("/obb/") != std::string::npos)
|
||||
{
|
||||
obbfile = new ZipFile(assetsPath);
|
||||
}
|
||||
|
||||
return FileUtils::init();
|
||||
}
|
||||
|
||||
std::string FileUtilsAndroid::getNewFilename(const std::string &filename) const
|
||||
{
|
||||
std::string newFileName = FileUtils::getNewFilename(filename);
|
||||
// ../xxx do not fix this path
|
||||
auto pos = newFileName.find("../");
|
||||
if (pos == std::string::npos || pos == 0)
|
||||
{
|
||||
return newFileName;
|
||||
}
|
||||
|
||||
std::vector<std::string> v(3);
|
||||
v.resize(0);
|
||||
auto change = false;
|
||||
size_t size = newFileName.size();
|
||||
size_t idx = 0;
|
||||
bool noexit = true;
|
||||
while (noexit)
|
||||
{
|
||||
pos = newFileName.find('/', idx);
|
||||
std::string tmp;
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
tmp = newFileName.substr(idx, size - idx);
|
||||
noexit = false;
|
||||
}else
|
||||
{
|
||||
tmp = newFileName.substr(idx, pos - idx + 1);
|
||||
}
|
||||
auto t = v.size();
|
||||
if (t > 0 && v[t-1].compare("../") != 0 &&
|
||||
(tmp.compare("../") == 0 || tmp.compare("..") == 0))
|
||||
{
|
||||
v.pop_back();
|
||||
change = true;
|
||||
}else
|
||||
{
|
||||
v.push_back(tmp);
|
||||
}
|
||||
idx = pos + 1;
|
||||
}
|
||||
|
||||
if (change)
|
||||
{
|
||||
newFileName.clear();
|
||||
for (auto &s : v)
|
||||
{
|
||||
newFileName.append(s);
|
||||
}
|
||||
}
|
||||
return newFileName;
|
||||
}
|
||||
|
||||
bool FileUtilsAndroid::isFileExistInternal(const std::string& strFilePath) const
|
||||
{
|
||||
if (strFilePath.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bFound = false;
|
||||
|
||||
// Check whether file exists in apk.
|
||||
if (strFilePath[0] != '/')
|
||||
{
|
||||
const char* s = strFilePath.c_str();
|
||||
|
||||
// Found "@assets/" at the beginning of the path and we don't want it
|
||||
if (strFilePath.find(ASSETS_FOLDER_NAME) == 0) s += strlen(ASSETS_FOLDER_NAME);
|
||||
if (obbfile && obbfile->fileExists(s))
|
||||
{
|
||||
bFound = true;
|
||||
}
|
||||
else if (FileUtilsAndroid::assetmanager)
|
||||
{
|
||||
AAsset* aa = AAssetManager_open(FileUtilsAndroid::assetmanager, s, AASSET_MODE_UNKNOWN);
|
||||
if (aa)
|
||||
{
|
||||
bFound = true;
|
||||
AAsset_close(aa);
|
||||
} else {
|
||||
// CCLOG("[AssetManager] ... in APK %s, found = false!", strFilePath.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FILE *fp = fopen(strFilePath.c_str(), "r");
|
||||
if (fp)
|
||||
{
|
||||
bFound = true;
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
return bFound;
|
||||
}
|
||||
|
||||
bool FileUtilsAndroid::isDirectoryExistInternal(const std::string& dirPath_) const
|
||||
{
|
||||
if (dirPath_.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string dirPath = dirPath_;
|
||||
if (dirPath[dirPath.length() - 1] == '/')
|
||||
{
|
||||
dirPath[dirPath.length() - 1] = '\0';
|
||||
}
|
||||
|
||||
// find absolute path in flash memory
|
||||
if (dirPath[0] == '/')
|
||||
{
|
||||
CCLOG("find in flash memory dirPath(%s)", dirPath.c_str());
|
||||
struct stat st;
|
||||
if (stat(dirPath.c_str(), &st) == 0)
|
||||
{
|
||||
return S_ISDIR(st.st_mode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// find it in apk's assets dir
|
||||
// Found "@assets/" at the beginning of the path and we don't want it
|
||||
CCLOG("find in apk dirPath(%s)", dirPath.c_str());
|
||||
const char* s = dirPath.c_str();
|
||||
if (dirPath.find(_defaultResRootPath) == 0)
|
||||
{
|
||||
s += _defaultResRootPath.length();
|
||||
}
|
||||
if (FileUtilsAndroid::assetmanager)
|
||||
{
|
||||
AAssetDir* aa = AAssetManager_openDir(FileUtilsAndroid::assetmanager, s);
|
||||
if (aa && AAssetDir_getNextFileName(aa))
|
||||
{
|
||||
AAssetDir_close(aa);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileUtilsAndroid::isAbsolutePath(const std::string& strPath) const
|
||||
{
|
||||
// On Android, there are two situations for full path.
|
||||
// 1) Files in APK, e.g. assets/path/path/file.png
|
||||
// 2) Files not in APK, e.g. /data/data/org.cocos2dx.hellocpp/cache/path/path/file.png, or /sdcard/path/path/file.png.
|
||||
// So these two situations need to be checked on Android.
|
||||
if (strPath[0] == '/' || strPath.find(ASSETS_FOLDER_NAME) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FileUtils::Status FileUtilsAndroid::getContents(const std::string& filename, ResizableBuffer* buffer)
|
||||
{
|
||||
if (filename.empty())
|
||||
return FileUtils::Status::NotExists;
|
||||
|
||||
std::string fullPath = fullPathForFilename(filename);
|
||||
if (fullPath.empty())
|
||||
return FileUtils::Status::NotExists;
|
||||
|
||||
if (fullPath[0] == '/')
|
||||
return FileUtils::getContents(fullPath, buffer);
|
||||
|
||||
std::string relativePath;
|
||||
size_t position = fullPath.find(ASSETS_FOLDER_NAME);
|
||||
if (0 == position) {
|
||||
// "@assets/" is at the beginning of the path and we don't want it
|
||||
relativePath += fullPath.substr(strlen(ASSETS_FOLDER_NAME));
|
||||
} else {
|
||||
relativePath = fullPath;
|
||||
}
|
||||
|
||||
if (obbfile)
|
||||
{
|
||||
if (obbfile->getFileData(relativePath, buffer))
|
||||
return FileUtils::Status::OK;
|
||||
}
|
||||
|
||||
if (nullptr == assetmanager) {
|
||||
LOGD("... FileUtilsAndroid::assetmanager is nullptr");
|
||||
return FileUtils::Status::NotInitialized;
|
||||
}
|
||||
|
||||
AAsset* asset = AAssetManager_open(assetmanager, relativePath.data(), AASSET_MODE_UNKNOWN);
|
||||
if (nullptr == asset) {
|
||||
LOGD("asset (%s) is nullptr", filename.c_str());
|
||||
return FileUtils::Status::OpenFailed;
|
||||
}
|
||||
|
||||
auto size = AAsset_getLength(asset);
|
||||
buffer->resize(size);
|
||||
|
||||
int readsize = AAsset_read(asset, buffer->buffer(), size);
|
||||
AAsset_close(asset);
|
||||
|
||||
if (readsize < size) {
|
||||
if (readsize >= 0)
|
||||
buffer->resize(readsize);
|
||||
return FileUtils::Status::ReadFailed;
|
||||
}
|
||||
|
||||
return FileUtils::Status::OK;
|
||||
}
|
||||
|
||||
std::string FileUtilsAndroid::getWritablePath() const
|
||||
{
|
||||
// Fix for Nexus 10 (Android 4.2 multi-user environment)
|
||||
// the path is retrieved through Java Context.getCacheDir() method
|
||||
std::string dir("");
|
||||
std::string tmp = JniHelper::callStaticStringMethod(JCLS_HELPER, "getWritablePath");
|
||||
|
||||
if (tmp.length() > 0)
|
||||
{
|
||||
dir.append(tmp).append("/");
|
||||
|
||||
return dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||
90
cocos2d-x/cocos/platform/android/CCFileUtils-android.h
Normal file
90
cocos2d-x/cocos/platform/android/CCFileUtils-android.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#ifndef __CC_FILEUTILS_ANDROID_H__
|
||||
#define __CC_FILEUTILS_ANDROID_H__
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include "base/ccMacros.h"
|
||||
#include "base/ccTypes.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "jni.h"
|
||||
#include "android/asset_manager.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
class ZipFile;
|
||||
|
||||
/**
|
||||
* @addtogroup platform
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! @brief Helper class to handle file operations
|
||||
class CC_DLL FileUtilsAndroid : public FileUtils
|
||||
{
|
||||
friend class FileUtils;
|
||||
public:
|
||||
FileUtilsAndroid();
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
*/
|
||||
virtual ~FileUtilsAndroid();
|
||||
|
||||
static void setassetmanager(AAssetManager* a);
|
||||
static AAssetManager* getAssetManager() { return assetmanager; }
|
||||
static ZipFile* getObbFile() { return obbfile; }
|
||||
|
||||
/* override functions */
|
||||
bool init() override;
|
||||
|
||||
virtual std::string getNewFilename(const std::string &filename) const override;
|
||||
|
||||
virtual FileUtils::Status getContents(const std::string& filename, ResizableBuffer* buffer) override;
|
||||
|
||||
virtual std::string getWritablePath() const override;
|
||||
virtual bool isAbsolutePath(const std::string& strPath) const override;
|
||||
|
||||
private:
|
||||
virtual bool isFileExistInternal(const std::string& strFilePath) const override;
|
||||
virtual bool isDirectoryExistInternal(const std::string& dirPath) const override;
|
||||
|
||||
static AAssetManager* assetmanager;
|
||||
static ZipFile* obbfile;
|
||||
};
|
||||
|
||||
// end of platform group
|
||||
/// @}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||
|
||||
#endif // __CC_FILEUTILS_ANDROID_H__
|
||||
79
cocos2d-x/cocos/platform/android/CCGL-android.h
Normal file
79
cocos2d-x/cocos/platform/android/CCGL-android.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __CCGL_H__
|
||||
#define __CCGL_H__
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||
|
||||
#define glClearDepth glClearDepthf
|
||||
#define glDeleteVertexArrays glDeleteVertexArraysOES
|
||||
#define glGenVertexArrays glGenVertexArraysOES
|
||||
#define glBindVertexArray glBindVertexArrayOES
|
||||
#define glMapBuffer glMapBufferOES
|
||||
#define glUnmapBuffer glUnmapBufferOES
|
||||
#define glTexImage3D glTexImage3DOES
|
||||
#define glCompressedTexImage3D glCompressedTexImage3DOES
|
||||
#define glCompressedTexSubImage3D glCompressedTexSubImage3DOES
|
||||
#define glTexSubImage3D glTexSubImage3DOES
|
||||
#define glDepthRange glDepthRangef
|
||||
#define glSubImage3D glSubImage3DOES
|
||||
|
||||
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
|
||||
#define GL_WRITE_ONLY GL_WRITE_ONLY_OES
|
||||
|
||||
// GL_GLEXT_PROTOTYPES isn't defined in glplatform.h on android ndk r7
|
||||
// we manually define it here
|
||||
#include <GLES2/gl2platform.h>
|
||||
#ifndef GL_GLEXT_PROTOTYPES
|
||||
#define GL_GLEXT_PROTOTYPES 1
|
||||
#endif
|
||||
|
||||
// normal process
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
// gl2.h doesn't define GLchar on Android
|
||||
typedef char GLchar;
|
||||
// android defines GL_BGRA_EXT but not GL_BRGA
|
||||
#ifndef GL_BGRA
|
||||
#define GL_BGRA 0x80E1
|
||||
#endif
|
||||
|
||||
//declare here while define in EGLView_android.cpp
|
||||
extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOESEXT;
|
||||
extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOESEXT;
|
||||
extern PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOESEXT;
|
||||
|
||||
#define glGenVertexArraysOES glGenVertexArraysOESEXT
|
||||
#define glBindVertexArrayOES glBindVertexArrayOESEXT
|
||||
#define glDeleteVertexArraysOES glDeleteVertexArraysOESEXT
|
||||
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||
|
||||
#endif // __CCGL_H__
|
||||
|
||||
68
cocos2d-x/cocos/platform/android/CCPlatformDefine-android.h
Normal file
68
cocos2d-x/cocos/platform/android/CCPlatformDefine-android.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __CCPLATFORMDEFINE_H__
|
||||
#define __CCPLATFORMDEFINE_H__
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#define CC_DLL
|
||||
|
||||
#define CC_NO_MESSAGE_PSEUDOASSERT(cond) \
|
||||
if (!(cond)) { \
|
||||
__android_log_print(ANDROID_LOG_ERROR, \
|
||||
"assert", \
|
||||
"%s function:%s line:%d", \
|
||||
__FILE__, __FUNCTION__, __LINE__); \
|
||||
}
|
||||
|
||||
#define CC_MESSAGE_PSEUDOASSERT(cond, msg) \
|
||||
if (!(cond)) { \
|
||||
__android_log_print(ANDROID_LOG_ERROR, \
|
||||
"assert", \
|
||||
"file:%s function:%s line:%d, %s", \
|
||||
__FILE__, __FUNCTION__, __LINE__, msg); \
|
||||
}
|
||||
|
||||
#define CC_ASSERT(cond) CC_NO_MESSAGE_PSEUDOASSERT(cond)
|
||||
|
||||
#define CC_UNUSED_PARAM(unusedparam) (void)unusedparam
|
||||
|
||||
/* Define NULL pointer value */
|
||||
#ifndef NULL
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||
|
||||
#endif /* __CCPLATFORMDEFINE_H__*/
|
||||
9
cocos2d-x/cocos/platform/android/java/.classpath
Normal file
9
cocos2d-x/cocos/platform/android/java/.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>
|
||||
33
cocos2d-x/cocos/platform/android/java/.project
Normal file
33
cocos2d-x/cocos/platform/android/java/.project
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>libcocos2dx</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.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,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.cocos2dx.lib"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-sdk android:minSdkVersion="9"/>
|
||||
|
||||
</manifest>
|
||||
83
cocos2d-x/cocos/platform/android/java/build.xml
Normal file
83
cocos2d-x/cocos/platform/android/java/build.xml
Normal file
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="cocos2dxandroid" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
||||
Binary file not shown.
BIN
cocos2d-x/cocos/platform/android/java/libs/okhttp-3.12.14.jar
Normal file
BIN
cocos2d-x/cocos/platform/android/java/libs/okhttp-3.12.14.jar
Normal file
Binary file not shown.
BIN
cocos2d-x/cocos/platform/android/java/libs/okio-1.15.0.jar
Normal file
BIN
cocos2d-x/cocos/platform/android/java/libs/okio-1.15.0.jar
Normal file
Binary file not shown.
20
cocos2d-x/cocos/platform/android/java/proguard-project.txt
Normal file
20
cocos2d-x/cocos/platform/android/java/proguard-project.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
# To enable ProGuard in your project, edit project.properties
|
||||
# to define the proguard.config property as described in that file.
|
||||
#
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the ProGuard
|
||||
# include property in project.properties.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
0
cocos2d-x/cocos/platform/android/java/res/.gitignore
vendored
Normal file
0
cocos2d-x/cocos/platform/android/java/res/.gitignore
vendored
Normal file
@@ -0,0 +1,510 @@
|
||||
/****************************************************************************
|
||||
* Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
|
||||
*
|
||||
* http://www.cocos.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Build;
|
||||
import android.text.TextPaint;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class CanvasRenderingContext2DImpl {
|
||||
|
||||
private static final String TAG = "CanvasContext2D";
|
||||
|
||||
private static final int TEXT_ALIGN_LEFT = 0;
|
||||
private static final int TEXT_ALIGN_CENTER = 1;
|
||||
private static final int TEXT_ALIGN_RIGHT = 2;
|
||||
|
||||
private static final int TEXT_BASELINE_TOP = 0;
|
||||
private static final int TEXT_BASELINE_MIDDLE = 1;
|
||||
private static final int TEXT_BASELINE_BOTTOM = 2;
|
||||
|
||||
private static WeakReference<Context> sContext;
|
||||
private TextPaint mTextPaint;
|
||||
private Paint mLinePaint;
|
||||
private Path mLinePath;
|
||||
private Canvas mCanvas = new Canvas();
|
||||
private Bitmap mBitmap;
|
||||
private int mTextAlign = TEXT_ALIGN_LEFT;
|
||||
private int mTextBaseline = TEXT_BASELINE_BOTTOM;
|
||||
private int mFillStyleR = 0;
|
||||
private int mFillStyleG = 0;
|
||||
private int mFillStyleB = 0;
|
||||
private int mFillStyleA = 255;
|
||||
|
||||
private int mStrokeStyleR = 0;
|
||||
private int mStrokeStyleG = 0;
|
||||
private int mStrokeStyleB = 0;
|
||||
private int mStrokeStyleA = 255;
|
||||
|
||||
private String mFontName = "Arial";
|
||||
private float mFontSize = 40.0f;
|
||||
private float mLineWidth = 0.0f;
|
||||
private static float _sApproximatingOblique = -0.25f;//please check paint api documentation
|
||||
private boolean mIsBoldFont = false;
|
||||
private boolean mIsItalicFont = false;
|
||||
private boolean mIsObliqueFont = false;
|
||||
private boolean mIsSmallCapsFontVariant = false;
|
||||
private String mLineCap = "butt";
|
||||
private String mLineJoin = "miter";
|
||||
|
||||
private class Size {
|
||||
Size(float w, float h) {
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
}
|
||||
|
||||
Size() {
|
||||
this.width = 0;
|
||||
this.height = 0;
|
||||
}
|
||||
public float width;
|
||||
public float height;
|
||||
}
|
||||
|
||||
private class Point {
|
||||
Point(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
Point() {
|
||||
this.x = this.y = 0.0f;
|
||||
}
|
||||
|
||||
Point(Point pt) {
|
||||
this.x = pt.x;
|
||||
this.y = pt.y;
|
||||
}
|
||||
|
||||
void set(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public float x;
|
||||
public float y;
|
||||
}
|
||||
|
||||
static void init(Context context) {
|
||||
sContext = new WeakReference<>(context);
|
||||
}
|
||||
|
||||
static void destroy() {
|
||||
sContext = null;
|
||||
}
|
||||
|
||||
private static HashMap<String, Typeface> sTypefaceCache = new HashMap<>();
|
||||
|
||||
// url is a full path started with '@assets/'
|
||||
private static void loadTypeface(String familyName, String url) {
|
||||
if (!sTypefaceCache.containsKey(familyName)) {
|
||||
try {
|
||||
Typeface typeface = null;
|
||||
if (url.startsWith("/")) {
|
||||
typeface = Typeface.createFromFile(url);
|
||||
} else if (sContext.get() != null) {
|
||||
final String prefix = "@assets/";
|
||||
if (url.startsWith(prefix)) {
|
||||
url = url.substring(prefix.length());
|
||||
}
|
||||
typeface = Typeface.createFromAsset(sContext.get().getAssets(), url);
|
||||
}
|
||||
|
||||
if (typeface != null) {
|
||||
sTypefaceCache.put(familyName, typeface);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// REFINE:: native should clear font cache before exiting game.
|
||||
private static void clearTypefaceCache() {
|
||||
sTypefaceCache.clear();
|
||||
}
|
||||
|
||||
private static TextPaint newPaint(String fontName, int fontSize, boolean enableBold, boolean enableItalic, boolean obliqueFont, boolean smallCapsFontVariant) {
|
||||
TextPaint paint = new TextPaint();
|
||||
paint.setTextSize(fontSize);
|
||||
paint.setAntiAlias(true);
|
||||
paint.setSubpixelText(true);
|
||||
|
||||
String key = fontName;
|
||||
if (enableBold) {
|
||||
key += "-Bold";
|
||||
paint.setFakeBoldText(true);
|
||||
}
|
||||
if (enableItalic) {
|
||||
key += "-Italic";
|
||||
}
|
||||
|
||||
Typeface typeFace;
|
||||
if (sTypefaceCache.containsKey(key)) {
|
||||
typeFace = sTypefaceCache.get(key);
|
||||
} else {
|
||||
int style = Typeface.NORMAL;
|
||||
if (enableBold && enableItalic) {
|
||||
style = Typeface.BOLD_ITALIC;
|
||||
} else if (enableBold) {
|
||||
style = Typeface.BOLD;
|
||||
} else if (enableItalic) {
|
||||
style = Typeface.ITALIC;
|
||||
}
|
||||
typeFace = Typeface.create(fontName, style);
|
||||
}
|
||||
paint.setTypeface(typeFace);
|
||||
if(obliqueFont) {
|
||||
paint.setTextSkewX(_sApproximatingOblique);
|
||||
}
|
||||
if(smallCapsFontVariant && Build.VERSION.SDK_INT >= 21) {
|
||||
Cocos2dxReflectionHelper.<Void>invokeInstanceMethod(paint,
|
||||
"setFontFeatureSettings",
|
||||
new Class[]{String.class},
|
||||
new Object[]{"smcp"});
|
||||
}
|
||||
return paint;
|
||||
}
|
||||
|
||||
private CanvasRenderingContext2DImpl() {
|
||||
// Log.d(TAG, "constructor");
|
||||
}
|
||||
|
||||
private void recreateBuffer(float w, float h) {
|
||||
// Log.d(TAG, "recreateBuffer:" + w + ", " + h);
|
||||
if (mBitmap != null) {
|
||||
mBitmap.recycle();
|
||||
}
|
||||
mBitmap = Bitmap.createBitmap((int)Math.ceil(w), (int)Math.ceil(h), Bitmap.Config.ARGB_8888);
|
||||
// FIXME: in MIX 2S, its API level is 28, but can not find invokeInstanceMethod. It seems
|
||||
// devices may not obey the specification, so comment the codes.
|
||||
// if (Build.VERSION.SDK_INT >= 19) {
|
||||
// Cocos2dxReflectionHelper.<Void>invokeInstanceMethod(mBitmap,
|
||||
// "setPremultiplied",
|
||||
// new Class[]{Boolean.class},
|
||||
// new Object[]{Boolean.FALSE});
|
||||
// }
|
||||
mCanvas.setBitmap(mBitmap);
|
||||
}
|
||||
|
||||
private void beginPath() {
|
||||
if (mLinePath == null) {
|
||||
mLinePath = new Path();
|
||||
}
|
||||
mLinePath.reset();
|
||||
}
|
||||
|
||||
private void closePath() {
|
||||
mLinePath.close();
|
||||
}
|
||||
|
||||
private void moveTo(float x, float y) {
|
||||
mLinePath.moveTo(x, y);
|
||||
}
|
||||
|
||||
private void lineTo(float x, float y) {
|
||||
mLinePath.lineTo(x, y);
|
||||
}
|
||||
|
||||
private void stroke() {
|
||||
if (mLinePaint == null) {
|
||||
mLinePaint = new Paint();
|
||||
mLinePaint.setAntiAlias(true);
|
||||
}
|
||||
|
||||
if(mLinePath == null) {
|
||||
mLinePath = new Path();
|
||||
}
|
||||
|
||||
mLinePaint.setARGB(mStrokeStyleA, mStrokeStyleR, mStrokeStyleG, mStrokeStyleB);
|
||||
mLinePaint.setStyle(Paint.Style.STROKE);
|
||||
mLinePaint.setStrokeWidth(mLineWidth);
|
||||
this.setStrokeCap(mLinePaint);
|
||||
this.setStrokeJoin(mLinePaint);
|
||||
mCanvas.drawPath(mLinePath, mLinePaint);
|
||||
}
|
||||
|
||||
private void setStrokeCap(Paint paint) {
|
||||
switch (mLineCap) {
|
||||
case "butt":
|
||||
paint.setStrokeCap(Paint.Cap.BUTT);
|
||||
break;
|
||||
case "round":
|
||||
paint.setStrokeCap(Paint.Cap.ROUND);
|
||||
break;
|
||||
case "square":
|
||||
paint.setStrokeCap(Paint.Cap.SQUARE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void setStrokeJoin(Paint paint) {
|
||||
switch (mLineJoin) {
|
||||
case "bevel":
|
||||
paint.setStrokeJoin(Paint.Join.BEVEL);
|
||||
break;
|
||||
case "round":
|
||||
paint.setStrokeJoin(Paint.Join.ROUND);
|
||||
break;
|
||||
case "miter":
|
||||
paint.setStrokeJoin(Paint.Join.MITER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void fill() {
|
||||
if (mLinePaint == null) {
|
||||
mLinePaint = new Paint();
|
||||
}
|
||||
|
||||
if(mLinePath == null) {
|
||||
mLinePath = new Path();
|
||||
}
|
||||
|
||||
mLinePaint.setARGB(mFillStyleA, mFillStyleR, mFillStyleG, mFillStyleB);
|
||||
mLinePaint.setStyle(Paint.Style.FILL);
|
||||
mCanvas.drawPath(mLinePath, mLinePaint);
|
||||
// workaround: draw a hairline to cover the border
|
||||
mLinePaint.setStrokeWidth(0);
|
||||
this.setStrokeCap(mLinePaint);
|
||||
this.setStrokeJoin(mLinePaint);
|
||||
mLinePaint.setStyle(Paint.Style.STROKE);
|
||||
mCanvas.drawPath(mLinePath, mLinePaint);
|
||||
mLinePaint.setStrokeWidth(mLineWidth);
|
||||
}
|
||||
|
||||
private void setLineCap(String lineCap) {
|
||||
mLineCap = lineCap;
|
||||
}
|
||||
|
||||
private void setLineJoin(String lineJoin) {
|
||||
mLineJoin = lineJoin;
|
||||
}
|
||||
|
||||
private void saveContext() {
|
||||
mCanvas.save();
|
||||
}
|
||||
|
||||
private void restoreContext() {
|
||||
// If there is no saved state, this method should do nothing.
|
||||
if (mCanvas.getSaveCount() > 1){
|
||||
mCanvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
private void rect(float x, float y, float w, float h) {
|
||||
// Log.d(TAG, "this: " + this + ", rect: " + x + ", " + y + ", " + w + ", " + h);
|
||||
beginPath();
|
||||
moveTo(x, y);
|
||||
lineTo(x, y + h);
|
||||
lineTo(x + w, y + h);
|
||||
lineTo(x + w, y);
|
||||
closePath();
|
||||
}
|
||||
|
||||
private void clearRect(float x, float y, float w, float h) {
|
||||
// Log.d(TAG, "this: " + this + ", clearRect: " + x + ", " + y + ", " + w + ", " + h);
|
||||
int clearSize = (int)(w * h);
|
||||
int[] clearColor = new int[clearSize];
|
||||
for (int i = 0; i < clearSize; ++i) {
|
||||
clearColor[i] = Color.TRANSPARENT;
|
||||
}
|
||||
mBitmap.setPixels(clearColor, 0, (int) w, (int) x, (int) y, (int) w, (int) h);
|
||||
}
|
||||
|
||||
private void createTextPaintIfNeeded() {
|
||||
if (mTextPaint == null) {
|
||||
mTextPaint = newPaint(mFontName, (int) mFontSize, mIsBoldFont, mIsItalicFont, mIsObliqueFont, mIsSmallCapsFontVariant);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillRect(float x, float y, float w, float h) {
|
||||
// Log.d(TAG, "fillRect: " + x + ", " + y + ", " + ", " + w + ", " + h);
|
||||
int pixelValue = (mFillStyleA & 0xff) << 24 | (mFillStyleR & 0xff) << 16 | (mFillStyleG & 0xff) << 8 | (mFillStyleB & 0xff);
|
||||
int fillSize = (int)(w * h);
|
||||
int[] fillColors = new int[fillSize];
|
||||
for (int i = 0; i < fillSize; ++i) {
|
||||
fillColors[i] = pixelValue;
|
||||
}
|
||||
mBitmap.setPixels(fillColors, 0, (int) w, (int)x, (int)y, (int)w, (int)h);
|
||||
}
|
||||
|
||||
private void scaleX(TextPaint textPaint, String text, float maxWidth) {
|
||||
if(maxWidth < Float.MIN_VALUE) return;
|
||||
float measureWidth = this.measureText(text);
|
||||
if((measureWidth - maxWidth) < Float.MIN_VALUE) return;
|
||||
float scaleX = maxWidth/measureWidth;
|
||||
textPaint.setTextScaleX(scaleX);
|
||||
}
|
||||
|
||||
private void fillText(String text, float x, float y, float maxWidth) {
|
||||
// Log.d(TAG, "this: " + this + ", fillText: " + text + ", " + x + ", " + y + ", " + ", " + maxWidth);
|
||||
createTextPaintIfNeeded();
|
||||
mTextPaint.setARGB(mFillStyleA, mFillStyleR, mFillStyleG, mFillStyleB);
|
||||
mTextPaint.setStyle(Paint.Style.FILL);
|
||||
scaleX(mTextPaint, text, maxWidth);
|
||||
Point pt = convertDrawPoint(new Point(x, y), text);
|
||||
mCanvas.drawText(text, pt.x, pt.y, mTextPaint);
|
||||
}
|
||||
|
||||
private void strokeText(String text, float x, float y, float maxWidth) {
|
||||
// Log.d(TAG, "strokeText: " + text + ", " + x + ", " + y + ", " + ", " + maxWidth);
|
||||
createTextPaintIfNeeded();
|
||||
mTextPaint.setARGB(mStrokeStyleA, mStrokeStyleR, mStrokeStyleG, mStrokeStyleB);
|
||||
mTextPaint.setStyle(Paint.Style.STROKE);
|
||||
mTextPaint.setStrokeWidth(mLineWidth);
|
||||
scaleX(mTextPaint, text, maxWidth);
|
||||
Point pt = convertDrawPoint(new Point(x, y), text);
|
||||
mCanvas.drawText(text, pt.x, pt.y, mTextPaint);
|
||||
}
|
||||
|
||||
private float measureText(String text) {
|
||||
createTextPaintIfNeeded();
|
||||
float ret = mTextPaint.measureText(text);
|
||||
// Log.d(TAG, "measureText: " + text + ", return: " + ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private Size measureTextReturnSize(String text) {
|
||||
createTextPaintIfNeeded();
|
||||
Paint.FontMetrics fm = mTextPaint.getFontMetrics();
|
||||
// Use descent & ascent for clipping the transparent region.
|
||||
// So don't use bottom & top which will make text be cut.
|
||||
return new Size(measureText(text), fm.descent - fm.ascent);
|
||||
}
|
||||
|
||||
private void updateFont(String fontName, float fontSize, boolean bold, boolean italic, boolean oblique, boolean smallCaps) {
|
||||
// Log.d(TAG, "updateFont: " + fontName + ", " + fontSize);
|
||||
mFontName = fontName;
|
||||
mFontSize = fontSize;
|
||||
mIsBoldFont = bold;
|
||||
mIsItalicFont = italic;
|
||||
mIsObliqueFont = oblique;
|
||||
mIsSmallCapsFontVariant = smallCaps;
|
||||
mTextPaint = null; // Reset paint to re-create paint object in createTextPaintIfNeeded
|
||||
}
|
||||
|
||||
private void setTextAlign(int align) {
|
||||
// Log.d(TAG, "setTextAlign: " + align);
|
||||
mTextAlign = align;
|
||||
}
|
||||
|
||||
private void setTextBaseline(int baseline) {
|
||||
// Log.d(TAG, "setTextBaseline: " + baseline);
|
||||
mTextBaseline = baseline;
|
||||
}
|
||||
|
||||
private void setFillStyle(float r, float g, float b, float a) {
|
||||
// Log.d(TAG, "setFillStyle: " + r + ", " + g + ", " + b + ", " + a);
|
||||
mFillStyleR = (int)(r * 255.0f);
|
||||
mFillStyleG = (int)(g * 255.0f);
|
||||
mFillStyleB = (int)(b * 255.0f);
|
||||
mFillStyleA = (int)(a * 255.0f);
|
||||
}
|
||||
|
||||
private void setStrokeStyle(float r, float g, float b, float a) {
|
||||
// Log.d(TAG, "setStrokeStyle: " + r + ", " + g + ", " + b + ", " + a);
|
||||
mStrokeStyleR = (int)(r * 255.0f);
|
||||
mStrokeStyleG = (int)(g * 255.0f);
|
||||
mStrokeStyleB = (int)(b * 255.0f);
|
||||
mStrokeStyleA = (int)(a * 255.0f);
|
||||
}
|
||||
|
||||
private void setLineWidth(float lineWidth) {
|
||||
mLineWidth = lineWidth;
|
||||
}
|
||||
|
||||
private void _fillImageData(byte[] imageData, float imageWidth, float imageHeight, float offsetX, float offsetY) {
|
||||
Log.d(TAG, "_fillImageData: ");
|
||||
int fillSize = (int) (imageWidth * imageHeight);
|
||||
int[] fillColors = new int[fillSize];
|
||||
int r, g, b, a;
|
||||
for (int i = 0; i < fillSize; ++i) {
|
||||
// imageData Pixel (RGBA) -> fillColors int (ARGB)
|
||||
r = ((int)imageData[4 * i + 0]) & 0xff;
|
||||
g = ((int)imageData[4 * i + 1]) & 0xff;
|
||||
b = ((int)imageData[4 * i + 2]) & 0xff;
|
||||
a = ((int)imageData[4 * i + 3]) & 0xff;
|
||||
fillColors[i] = (a & 0xff) << 24 | (r & 0xff) << 16 | (g & 0xff) << 8 | (b & 0xff);
|
||||
}
|
||||
mBitmap.setPixels(fillColors, 0, (int) imageWidth, (int) offsetX, (int) offsetY, (int) imageWidth, (int) imageHeight);
|
||||
}
|
||||
|
||||
private Point convertDrawPoint(final Point point, String text) {
|
||||
// The parameter 'point' is located at left-bottom position.
|
||||
// Need to adjust 'point' according 'text align' & 'text base line'.
|
||||
Point ret = new Point(point);
|
||||
Size textSize = measureTextReturnSize(text);
|
||||
// Log.d(TAG,"textSize: " + textSize.width + ", " + textSize.height);
|
||||
|
||||
if (mTextAlign == TEXT_ALIGN_CENTER)
|
||||
{
|
||||
ret.x -= textSize.width / 2;
|
||||
}
|
||||
else if (mTextAlign == TEXT_ALIGN_RIGHT)
|
||||
{
|
||||
ret.x -= textSize.width;
|
||||
}
|
||||
|
||||
if (mTextBaseline == TEXT_BASELINE_TOP)
|
||||
{
|
||||
ret.y += textSize.height;
|
||||
}
|
||||
else if (mTextBaseline == TEXT_BASELINE_MIDDLE)
|
||||
{
|
||||
ret.y += textSize.height / 2;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private byte[] getDataRef() {
|
||||
// Log.d(TAG, "this: " + this + ", getDataRef ...");
|
||||
if (mBitmap != null) {
|
||||
final int len = mBitmap.getWidth() * mBitmap.getHeight() * 4;
|
||||
final byte[] pixels = new byte[len];
|
||||
final ByteBuffer buf = ByteBuffer.wrap(pixels);
|
||||
buf.order(ByteOrder.nativeOrder());
|
||||
mBitmap.copyPixelsToBuffer(buf);
|
||||
|
||||
return pixels;
|
||||
}
|
||||
|
||||
Log.e(TAG, "getDataRef return null");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2013 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
|
||||
public class Cocos2dxAccelerometer implements SensorEventListener {
|
||||
// ===========================================================
|
||||
// Constants
|
||||
// ===========================================================
|
||||
|
||||
private static final String TAG = Cocos2dxAccelerometer.class.getSimpleName();
|
||||
|
||||
// ===========================================================
|
||||
// Fields
|
||||
// ===========================================================
|
||||
private final Context mContext;
|
||||
private final SensorManager mSensorManager;
|
||||
private final Sensor mAcceleration;
|
||||
private final Sensor mAccelerationIncludingGravity;
|
||||
private final Sensor mGyroscope;
|
||||
private int mSamplingPeriodUs = SensorManager.SENSOR_DELAY_GAME;
|
||||
|
||||
class Acceleration {
|
||||
public float x = 0.0f;
|
||||
public float y = 0.0f;
|
||||
public float z = 0.0f;
|
||||
}
|
||||
|
||||
class RotationRate {
|
||||
public float alpha = 0.0f;
|
||||
public float beta = 0.0f;
|
||||
public float gamma = 0.0f;
|
||||
}
|
||||
|
||||
class DeviceMotionEvent {
|
||||
public Acceleration acceleration = new Acceleration();
|
||||
public Acceleration accelerationIncludingGravity = new Acceleration();
|
||||
public RotationRate rotationRate = new RotationRate();
|
||||
}
|
||||
|
||||
private DeviceMotionEvent mDeviceMotionEvent = new DeviceMotionEvent();
|
||||
|
||||
// ===========================================================
|
||||
// Constructors
|
||||
// ===========================================================
|
||||
|
||||
public Cocos2dxAccelerometer(final Context context) {
|
||||
mContext = context;
|
||||
|
||||
mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
|
||||
mAcceleration = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
mAccelerationIncludingGravity = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
|
||||
mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Getter & Setter
|
||||
// ===========================================================
|
||||
public void enable() {
|
||||
mSensorManager.registerListener(this, mAcceleration, mSamplingPeriodUs);
|
||||
mSensorManager.registerListener(this, mAccelerationIncludingGravity, mSamplingPeriodUs);
|
||||
mSensorManager.registerListener(this, mGyroscope, mSamplingPeriodUs);
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
this.mSensorManager.unregisterListener(this);
|
||||
}
|
||||
|
||||
public void setInterval(float interval) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= 11) {
|
||||
mSamplingPeriodUs = (int) (interval * 1000000);
|
||||
}
|
||||
disable();
|
||||
enable();
|
||||
}
|
||||
|
||||
public DeviceMotionEvent getDeviceMotionEvent() {
|
||||
return mDeviceMotionEvent;
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Methods for/from SuperClass/Interfaces
|
||||
// ===========================================================
|
||||
@Override
|
||||
public void onSensorChanged(final SensorEvent sensorEvent) {
|
||||
int type = sensorEvent.sensor.getType();
|
||||
if (type == Sensor.TYPE_ACCELEROMETER) {
|
||||
mDeviceMotionEvent.accelerationIncludingGravity.x = sensorEvent.values[0];
|
||||
mDeviceMotionEvent.accelerationIncludingGravity.y = sensorEvent.values[1];
|
||||
mDeviceMotionEvent.accelerationIncludingGravity.z = sensorEvent.values[2];
|
||||
}
|
||||
else if (type == Sensor.TYPE_LINEAR_ACCELERATION) {
|
||||
mDeviceMotionEvent.acceleration.x = sensorEvent.values[0];
|
||||
mDeviceMotionEvent.acceleration.y = sensorEvent.values[1];
|
||||
mDeviceMotionEvent.acceleration.z = sensorEvent.values[2];
|
||||
}
|
||||
else if (type == Sensor.TYPE_GYROSCOPE) {
|
||||
// The unit is rad/s, need to be converted to deg/s
|
||||
mDeviceMotionEvent.rotationRate.alpha = (float)Math.toDegrees(sensorEvent.values[0]);
|
||||
mDeviceMotionEvent.rotationRate.beta = (float)Math.toDegrees(sensorEvent.values[1]);
|
||||
mDeviceMotionEvent.rotationRate.gamma = (float)Math.toDegrees(sensorEvent.values[2]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(final Sensor sensor, final int accuracy) {
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Methods
|
||||
// Native method called from Cocos2dxGLSurfaceView (To be in the same thread)
|
||||
// ===========================================================
|
||||
|
||||
public static native void onSensorChanged(final float x, final float y, final float z, final long timestamp);
|
||||
|
||||
// ===========================================================
|
||||
// Inner and Anonymous Classes
|
||||
// ===========================================================
|
||||
}
|
||||
@@ -0,0 +1,652 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2013 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.media.AudioManager;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.preference.PreferenceManager.OnActivityResultListener;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.cocos2dx.lib.Cocos2dxHelper.Cocos2dxHelperListener;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import javax.microedition.khronos.egl.EGL10;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.egl.EGLDisplay;
|
||||
|
||||
public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelperListener {
|
||||
// ===========================================================
|
||||
// Constants
|
||||
// ===========================================================
|
||||
|
||||
private final static String TAG = Cocos2dxActivity.class.getSimpleName();
|
||||
|
||||
// ===========================================================
|
||||
// Fields
|
||||
// ===========================================================
|
||||
private static Cocos2dxActivity sContext = null;
|
||||
|
||||
protected FrameLayout mFrameLayout = null;
|
||||
|
||||
private Cocos2dxGLSurfaceView mGLSurfaceView = null;
|
||||
private int[] mGLContextAttrs = null;
|
||||
private Cocos2dxHandler mHandler = null;
|
||||
private Cocos2dxVideoHelper mVideoHelper = null;
|
||||
private Cocos2dxWebViewHelper mWebViewHelper = null;
|
||||
private boolean hasFocus = false;
|
||||
private Cocos2dxEditBox mEditBox = null;
|
||||
private boolean gainAudioFocus = false;
|
||||
private boolean paused = true;
|
||||
|
||||
// DEBUG VIEW BEGIN
|
||||
private LinearLayout mLinearLayoutForDebugView;
|
||||
private TextView mFPSTextView;
|
||||
private TextView mJSBInvocationTextView;
|
||||
private TextView mGLOptModeTextView;
|
||||
private TextView mGameInfoTextView_0;
|
||||
private TextView mGameInfoTextView_1;
|
||||
private TextView mGameInfoTextView_2;
|
||||
// DEBUG VIEW END
|
||||
|
||||
private Cocos2dxOrientationHelper mCocos2dxOrientationHelper = null;
|
||||
// ===========================================================
|
||||
// Inner class
|
||||
// ===========================================================
|
||||
|
||||
public class Cocos2dxEGLConfigChooser implements GLSurfaceView.EGLConfigChooser {
|
||||
protected int[] configAttribs;
|
||||
public Cocos2dxEGLConfigChooser(int redSize, int greenSize, int blueSize, int alphaSize, int depthSize, int stencilSize)
|
||||
{
|
||||
configAttribs = new int[] {redSize, greenSize, blueSize, alphaSize, depthSize, stencilSize};
|
||||
}
|
||||
public Cocos2dxEGLConfigChooser(int[] attribs)
|
||||
{
|
||||
configAttribs = attribs;
|
||||
}
|
||||
|
||||
private int findConfigAttrib(EGL10 egl, EGLDisplay display,
|
||||
EGLConfig config, int attribute, int defaultValue) {
|
||||
int[] value = new int[1];
|
||||
if (egl.eglGetConfigAttrib(display, config, attribute, value)) {
|
||||
return value[0];
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
class ConfigValue implements Comparable<ConfigValue> {
|
||||
public EGLConfig config = null;
|
||||
public int[] configAttribs = null;
|
||||
public int value = 0;
|
||||
private void calcValue() {
|
||||
// depth factor 29bit and [6,12)bit
|
||||
if (configAttribs[4] > 0) {
|
||||
value = value + (1 << 29) + ((configAttribs[4]%64) << 6);
|
||||
}
|
||||
// stencil factor 28bit and [0, 6)bit
|
||||
if (configAttribs[5] > 0) {
|
||||
value = value + (1 << 28) + ((configAttribs[5]%64));
|
||||
}
|
||||
// alpha factor 30bit and [24, 28)bit
|
||||
if (configAttribs[3] > 0) {
|
||||
value = value + (1 << 30) + ((configAttribs[3]%16) << 24);
|
||||
}
|
||||
// green factor [20, 24)bit
|
||||
if (configAttribs[1] > 0) {
|
||||
value = value + ((configAttribs[1]%16) << 20);
|
||||
}
|
||||
// blue factor [16, 20)bit
|
||||
if (configAttribs[2] > 0) {
|
||||
value = value + ((configAttribs[2]%16) << 16);
|
||||
}
|
||||
// red factor [12, 16)bit
|
||||
if (configAttribs[0] > 0) {
|
||||
value = value + ((configAttribs[0]%16) << 12);
|
||||
}
|
||||
}
|
||||
|
||||
public ConfigValue(int[] attribs) {
|
||||
configAttribs = attribs;
|
||||
calcValue();
|
||||
}
|
||||
|
||||
public ConfigValue(EGL10 egl, EGLDisplay display, EGLConfig config) {
|
||||
this.config = config;
|
||||
configAttribs = new int[6];
|
||||
configAttribs[0] = findConfigAttrib(egl, display, config, EGL10.EGL_RED_SIZE, 0);
|
||||
configAttribs[1] = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0);
|
||||
configAttribs[2] = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0);
|
||||
configAttribs[3] = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0);
|
||||
configAttribs[4] = findConfigAttrib(egl, display, config, EGL10.EGL_DEPTH_SIZE, 0);
|
||||
configAttribs[5] = findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0);
|
||||
calcValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ConfigValue another) {
|
||||
if (value < another.value) {
|
||||
return -1;
|
||||
} else if (value > another.value) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{ color: " + configAttribs[3] + configAttribs[2] + configAttribs[1] + configAttribs[0] +
|
||||
"; depth: " + configAttribs[4] + "; stencil: " + configAttribs[5] + ";}";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display)
|
||||
{
|
||||
int[] EGLattribs = {
|
||||
EGL10.EGL_RED_SIZE, configAttribs[0],
|
||||
EGL10.EGL_GREEN_SIZE, configAttribs[1],
|
||||
EGL10.EGL_BLUE_SIZE, configAttribs[2],
|
||||
EGL10.EGL_ALPHA_SIZE, configAttribs[3],
|
||||
EGL10.EGL_DEPTH_SIZE, configAttribs[4],
|
||||
EGL10.EGL_STENCIL_SIZE,configAttribs[5],
|
||||
EGL10.EGL_RENDERABLE_TYPE, 4, //EGL_OPENGL_ES2_BIT
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
EGLConfig[] configs = new EGLConfig[1];
|
||||
int[] numConfigs = new int[1];
|
||||
boolean eglChooseResult = egl.eglChooseConfig(display, EGLattribs, configs, 1, numConfigs);
|
||||
if (eglChooseResult && numConfigs[0] > 0)
|
||||
{
|
||||
return configs[0];
|
||||
}
|
||||
|
||||
// there's no config match the specific configAttribs, we should choose a closest one
|
||||
int[] EGLV2attribs = {
|
||||
EGL10.EGL_RENDERABLE_TYPE, 4, //EGL_OPENGL_ES2_BIT
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
eglChooseResult = egl.eglChooseConfig(display, EGLV2attribs, null, 0, numConfigs);
|
||||
if(eglChooseResult && numConfigs[0] > 0) {
|
||||
int num = numConfigs[0];
|
||||
ConfigValue[] cfgVals = new ConfigValue[num];
|
||||
|
||||
// convert all config to ConfigValue
|
||||
configs = new EGLConfig[num];
|
||||
egl.eglChooseConfig(display, EGLV2attribs, configs, num, numConfigs);
|
||||
for (int i = 0; i < num; ++i) {
|
||||
cfgVals[i] = new ConfigValue(egl, display, configs[i]);
|
||||
}
|
||||
|
||||
ConfigValue e = new ConfigValue(configAttribs);
|
||||
// bin search
|
||||
int lo = 0;
|
||||
int hi = num;
|
||||
int mi;
|
||||
while (lo < hi - 1) {
|
||||
mi = (lo + hi) / 2;
|
||||
if (e.compareTo(cfgVals[mi]) < 0) {
|
||||
hi = mi;
|
||||
} else {
|
||||
lo = mi;
|
||||
}
|
||||
}
|
||||
if (lo != num - 1) {
|
||||
lo = lo + 1;
|
||||
}
|
||||
Log.w("cocos2d", "Can't find EGLConfig match: " + e + ", instead of closest one:" + cfgVals[lo]);
|
||||
return cfgVals[lo].config;
|
||||
}
|
||||
|
||||
Log.e(DEVICE_POLICY_SERVICE, "Can not select an EGLConfig for rendering.");
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Member methods
|
||||
// ===========================================================
|
||||
|
||||
public Cocos2dxGLSurfaceView getGLSurfaceView(){
|
||||
return mGLSurfaceView;
|
||||
}
|
||||
public static Context getContext() {
|
||||
return sContext;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
ViewGroup.LayoutParams frameLayoutParams =
|
||||
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
mFrameLayout = new FrameLayout(this);
|
||||
mFrameLayout.setLayoutParams(frameLayoutParams);
|
||||
|
||||
Cocos2dxRenderer renderer = this.addSurfaceView();
|
||||
this.addDebugInfo(renderer);
|
||||
|
||||
|
||||
// Should create EditBox after adding SurfaceView, or EditBox will be hidden by SurfaceView.
|
||||
mEditBox = new Cocos2dxEditBox(this, mFrameLayout);
|
||||
|
||||
// Set frame layout as the content view
|
||||
setContentView(mFrameLayout);
|
||||
|
||||
WindowManager.LayoutParams lp = getWindow().getAttributes();
|
||||
try {
|
||||
Field field = lp.getClass().getField("layoutInDisplayCutoutMode");
|
||||
//Field constValue = lp.getClass().getDeclaredField("LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER");
|
||||
Field constValue = lp.getClass().getDeclaredField("LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES");
|
||||
field.setInt(lp, constValue.getInt(null));
|
||||
|
||||
// https://developer.android.com/training/system-ui/immersive
|
||||
int flag = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
|
||||
|
||||
flag |= View.class.getDeclaredField("SYSTEM_UI_FLAG_IMMERSIVE_STICKY").getInt(null);
|
||||
View view = getWindow().getDecorView();
|
||||
view.setSystemUiVisibility(flag);
|
||||
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
mCocos2dxOrientationHelper = new Cocos2dxOrientationHelper(this);
|
||||
}
|
||||
|
||||
public void setKeepScreenOn(boolean value) {
|
||||
final boolean newValue = value;
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mGLSurfaceView.setKeepScreenOn(newValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setEnableAudioFocusGain(boolean value) {
|
||||
if(gainAudioFocus != value) {
|
||||
if(!paused) {
|
||||
if (value)
|
||||
Cocos2dxAudioFocusManager.registerAudioFocusListener(this);
|
||||
else
|
||||
Cocos2dxAudioFocusManager.unregisterAudioFocusListener(this);
|
||||
}
|
||||
gainAudioFocus = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Cocos2dxGLSurfaceView onCreateView() {
|
||||
Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
|
||||
//this line is need on some device if we specify an alpha bits
|
||||
if(this.mGLContextAttrs[3] > 0) glSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
|
||||
|
||||
Cocos2dxEGLConfigChooser chooser = new Cocos2dxEGLConfigChooser(this.mGLContextAttrs);
|
||||
glSurfaceView.setEGLConfigChooser(chooser);
|
||||
|
||||
return glSurfaceView;
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Override functions
|
||||
// ===========================================================
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
Log.d(TAG, "Cocos2dxActivity onCreate: " + this + ", savedInstanceState: " + savedInstanceState);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Workaround in https://stackoverflow.com/questions/16283079/re-launch-of-activity-on-home-button-but-only-the-first-time/16447508
|
||||
if (!isTaskRoot()) {
|
||||
// Android launched another instance of the root activity into an existing task
|
||||
// so just quietly finish and go away, dropping the user back into the activity
|
||||
// at the top of the stack (ie: the last state of this task)
|
||||
finish();
|
||||
Log.w(TAG, "[Workaround] Ignore the activity started from icon!");
|
||||
return;
|
||||
}
|
||||
|
||||
Utils.setActivity(this);
|
||||
|
||||
Utils.hideVirtualButton();
|
||||
|
||||
Cocos2dxHelper.registerBatteryLevelReceiver(this);
|
||||
|
||||
onLoadNativeLibraries();
|
||||
|
||||
sContext = this;
|
||||
this.mHandler = new Cocos2dxHandler(this);
|
||||
|
||||
Cocos2dxHelper.init(this);
|
||||
CanvasRenderingContext2DImpl.init(this);
|
||||
|
||||
this.mGLContextAttrs = getGLContextAttrs();
|
||||
this.init();
|
||||
|
||||
if (mVideoHelper == null) {
|
||||
mVideoHelper = new Cocos2dxVideoHelper(this, mFrameLayout);
|
||||
}
|
||||
|
||||
if(mWebViewHelper == null){
|
||||
mWebViewHelper = new Cocos2dxWebViewHelper(mFrameLayout);
|
||||
}
|
||||
|
||||
Window window = this.getWindow();
|
||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
||||
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
Log.d(TAG, "onResume()");
|
||||
paused = false;
|
||||
super.onResume();
|
||||
if(gainAudioFocus)
|
||||
Cocos2dxAudioFocusManager.registerAudioFocusListener(this);
|
||||
Utils.hideVirtualButton();
|
||||
resumeIfHasFocus();
|
||||
mCocos2dxOrientationHelper.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
Log.d(TAG, "onWindowFocusChanged() hasFocus=" + hasFocus);
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
|
||||
this.hasFocus = hasFocus;
|
||||
resumeIfHasFocus();
|
||||
}
|
||||
|
||||
private void resumeIfHasFocus() {
|
||||
if(hasFocus && !paused) {
|
||||
Utils.hideVirtualButton();
|
||||
Cocos2dxHelper.onResume();
|
||||
mGLSurfaceView.onResume();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
Log.d(TAG, "onPause()");
|
||||
paused = true;
|
||||
super.onPause();
|
||||
if(gainAudioFocus)
|
||||
Cocos2dxAudioFocusManager.unregisterAudioFocusListener(this);
|
||||
Cocos2dxHelper.onPause();
|
||||
mGLSurfaceView.onPause();
|
||||
mCocos2dxOrientationHelper.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
// Workaround in https://stackoverflow.com/questions/16283079/re-launch-of-activity-on-home-button-but-only-the-first-time/16447508
|
||||
if (!isTaskRoot()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(gainAudioFocus)
|
||||
Cocos2dxAudioFocusManager.unregisterAudioFocusListener(this);
|
||||
Cocos2dxHelper.unregisterBatteryLevelReceiver(this);;
|
||||
CanvasRenderingContext2DImpl.destroy();
|
||||
|
||||
Log.d(TAG, "Cocos2dxActivity onDestroy: " + this + ", mGLSurfaceView" + mGLSurfaceView);
|
||||
if (mGLSurfaceView != null) {
|
||||
Cocos2dxHelper.terminateProcess();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDialog(final String pTitle, final String pMessage) {
|
||||
Message msg = new Message();
|
||||
msg.what = Cocos2dxHandler.HANDLER_SHOW_DIALOG;
|
||||
msg.obj = new Cocos2dxHandler.DialogMessage(pTitle, pMessage);
|
||||
this.mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runOnGLThread(final Runnable runnable) {
|
||||
this.mGLSurfaceView.queueEvent(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
for (OnActivityResultListener listener : Cocos2dxHelper.getOnActivityResultListeners()) {
|
||||
listener.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Protected and private methods
|
||||
// ===========================================================
|
||||
|
||||
protected void onLoadNativeLibraries() {
|
||||
try {
|
||||
ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
|
||||
Bundle bundle = ai.metaData;
|
||||
String libName = bundle.getString("android.app.lib_name");
|
||||
System.loadLibrary(libName);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private Cocos2dxRenderer addSurfaceView() {
|
||||
this.mGLSurfaceView = this.onCreateView();
|
||||
this.mGLSurfaceView.setPreserveEGLContextOnPause(true);
|
||||
// Should set to transparent, or it will hide EditText
|
||||
// https://stackoverflow.com/questions/2978290/androids-edittext-is-hidden-when-the-virtual-keyboard-is-shown-and-a-surfacevie
|
||||
mGLSurfaceView.setBackgroundColor(Color.TRANSPARENT);
|
||||
// Switch to supported OpenGL (ARGB888) mode on emulator
|
||||
if (isAndroidEmulator())
|
||||
this.mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
|
||||
|
||||
Cocos2dxRenderer renderer = new Cocos2dxRenderer();
|
||||
this.mGLSurfaceView.setCocos2dxRenderer(renderer);
|
||||
|
||||
mFrameLayout.addView(this.mGLSurfaceView);
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
private void addDebugInfo(Cocos2dxRenderer renderer) {
|
||||
LinearLayout.LayoutParams linearLayoutParam = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
linearLayoutParam.setMargins(30, 0, 0, 0);
|
||||
Cocos2dxHelper.setOnGameInfoUpdatedListener(new Cocos2dxHelper.OnGameInfoUpdatedListener() {
|
||||
@Override
|
||||
public void onFPSUpdated(float fps) {
|
||||
Cocos2dxActivity.this.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mFPSTextView != null) {
|
||||
mFPSTextView.setText("FPS: " + (int)Math.ceil(fps));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onJSBInvocationCountUpdated(int count) {
|
||||
Cocos2dxActivity.this.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mJSBInvocationTextView != null) {
|
||||
mJSBInvocationTextView.setText("JSB: " + count);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpenDebugView() {
|
||||
Cocos2dxActivity.this.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mLinearLayoutForDebugView != null || mFrameLayout == null) {
|
||||
Log.e(TAG, "onOpenDebugView: failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
mLinearLayoutForDebugView = new LinearLayout(Cocos2dxActivity.this);
|
||||
mLinearLayoutForDebugView.setOrientation(LinearLayout.VERTICAL);
|
||||
mFrameLayout.addView(mLinearLayoutForDebugView);
|
||||
|
||||
mFPSTextView = new TextView(Cocos2dxActivity.this);
|
||||
mFPSTextView.setBackgroundColor(Color.RED);
|
||||
mFPSTextView.setTextColor(Color.WHITE);
|
||||
mLinearLayoutForDebugView.addView(mFPSTextView, linearLayoutParam);
|
||||
|
||||
mJSBInvocationTextView = new TextView(Cocos2dxActivity.this);
|
||||
mJSBInvocationTextView.setBackgroundColor(Color.GREEN);
|
||||
mJSBInvocationTextView.setTextColor(Color.WHITE);
|
||||
mLinearLayoutForDebugView.addView(mJSBInvocationTextView, linearLayoutParam);
|
||||
|
||||
mGLOptModeTextView = new TextView(Cocos2dxActivity.this);
|
||||
mGLOptModeTextView.setBackgroundColor(Color.BLUE);
|
||||
mGLOptModeTextView.setTextColor(Color.WHITE);
|
||||
mGLOptModeTextView.setText("GL Opt: Enabled");
|
||||
mLinearLayoutForDebugView.addView(mGLOptModeTextView, linearLayoutParam);
|
||||
|
||||
mGameInfoTextView_0 = new TextView(Cocos2dxActivity.this);
|
||||
mGameInfoTextView_0.setBackgroundColor(Color.RED);
|
||||
mGameInfoTextView_0.setTextColor(Color.WHITE);
|
||||
mLinearLayoutForDebugView.addView(mGameInfoTextView_0, linearLayoutParam);
|
||||
|
||||
mGameInfoTextView_1 = new TextView(Cocos2dxActivity.this);
|
||||
mGameInfoTextView_1.setBackgroundColor(Color.GREEN);
|
||||
mGameInfoTextView_1.setTextColor(Color.WHITE);
|
||||
mLinearLayoutForDebugView.addView(mGameInfoTextView_1, linearLayoutParam);
|
||||
|
||||
mGameInfoTextView_2 = new TextView(Cocos2dxActivity.this);
|
||||
mGameInfoTextView_2.setBackgroundColor(Color.BLUE);
|
||||
mGameInfoTextView_2.setTextColor(Color.WHITE);
|
||||
mLinearLayoutForDebugView.addView(mGameInfoTextView_2, linearLayoutParam);
|
||||
}
|
||||
});
|
||||
|
||||
renderer.showFPS();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisableBatchGLCommandsToNative() {
|
||||
Cocos2dxActivity.this.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mGLOptModeTextView != null) {
|
||||
mGLOptModeTextView.setText("GL Opt: Disabled");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGameInfoUpdated_0(final String text) {
|
||||
|
||||
Cocos2dxActivity.this.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mGameInfoTextView_0 != null) {
|
||||
mGameInfoTextView_0.setText(text);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGameInfoUpdated_1(String text) {
|
||||
|
||||
Cocos2dxActivity.this.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mGameInfoTextView_1 != null) {
|
||||
mGameInfoTextView_1.setText(text);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGameInfoUpdated_2(String text) {
|
||||
|
||||
Cocos2dxActivity.this.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mGameInfoTextView_2 != null) {
|
||||
mGameInfoTextView_2.setText(text);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private final static boolean isAndroidEmulator() {
|
||||
String model = Build.MODEL;
|
||||
Log.d(TAG, "model=" + model);
|
||||
String product = Build.PRODUCT;
|
||||
Log.d(TAG, "product=" + product);
|
||||
boolean isEmulator = false;
|
||||
if (product != null) {
|
||||
isEmulator = product.equals("sdk") || product.contains("_sdk") || product.contains("sdk_");
|
||||
}
|
||||
Log.d(TAG, "isEmulator=" + isEmulator);
|
||||
return isEmulator;
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Native methods
|
||||
// ===========================================================
|
||||
|
||||
//native method,call GLViewImpl::getGLContextAttrs() to get the OpenGL ES context attributions
|
||||
private static native int[] getGLContextAttrs();
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/****************************************************************************
|
||||
* Copyright (c) 2016 Chukong Technologies Inc.
|
||||
* Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
*
|
||||
* http://www.cocos2d-x.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
import android.util.Log;
|
||||
|
||||
class Cocos2dxAudioFocusManager {
|
||||
|
||||
private final static String TAG = "AudioFocusManager";
|
||||
// Audio focus values synchronized with which in cocos/platform/android/javaactivity-android.cpp
|
||||
private final static int AUDIOFOCUS_GAIN = 0;
|
||||
private final static int AUDIOFOCUS_LOST = 1;
|
||||
private final static int AUDIOFOCUS_LOST_TRANSIENT = 2;
|
||||
private final static int AUDIOFOCUS_LOST_TRANSIENT_CAN_DUCK = 3;
|
||||
|
||||
private static AudioManager.OnAudioFocusChangeListener sAfChangeListener =
|
||||
new AudioManager.OnAudioFocusChangeListener() {
|
||||
public void onAudioFocusChange(int focusChange) {
|
||||
|
||||
Log.d(TAG, "onAudioFocusChange: " + focusChange + ", thread: " + Thread.currentThread().getName());
|
||||
|
||||
if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
|
||||
// Permanent loss of audio focus
|
||||
// Pause playback immediately
|
||||
Log.d(TAG, "Pause music by AUDIOFOCUS_LOSS");
|
||||
Cocos2dxHelper.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
nativeOnAudioFocusChange(AUDIOFOCUS_LOST);
|
||||
}
|
||||
});
|
||||
|
||||
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
|
||||
// Pause playback
|
||||
Log.d(TAG, "Pause music by AUDIOFOCUS_LOSS_TRANSILENT");
|
||||
Cocos2dxHelper.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
nativeOnAudioFocusChange(AUDIOFOCUS_LOST_TRANSIENT);
|
||||
}
|
||||
});
|
||||
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
|
||||
// Lower the volume, keep playing
|
||||
Log.d(TAG, "Lower the volume, keep playing by AUDIOFOCUS_LOSS_TRANSILENT_CAN_DUCK");
|
||||
Cocos2dxHelper.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
nativeOnAudioFocusChange(AUDIOFOCUS_LOST_TRANSIENT_CAN_DUCK);
|
||||
}
|
||||
});
|
||||
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
|
||||
// Your app has been granted audio focus again
|
||||
// Raise volume to normal, restart playback if necessary
|
||||
Log.d(TAG, "Resume music by AUDIOFOCUS_GAIN");
|
||||
Cocos2dxHelper.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
nativeOnAudioFocusChange(AUDIOFOCUS_GAIN);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static boolean registerAudioFocusListener(Context context) {
|
||||
AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
// Request audio focus for playback
|
||||
int result = am.requestAudioFocus(sAfChangeListener,
|
||||
// Use the music stream.
|
||||
AudioManager.STREAM_MUSIC,
|
||||
// Request permanent focus.
|
||||
AudioManager.AUDIOFOCUS_GAIN);
|
||||
|
||||
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||
Log.d(TAG, "requestAudioFocus succeed");
|
||||
return true;
|
||||
}
|
||||
|
||||
Log.e(TAG, "requestAudioFocus failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
static void unregisterAudioFocusListener(Context context) {
|
||||
AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||
int result = am.abandonAudioFocus(sAfChangeListener);
|
||||
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||
Log.d(TAG, "abandonAudioFocus succeed!");
|
||||
} else {
|
||||
Log.e(TAG, "abandonAudioFocus failed!");
|
||||
}
|
||||
|
||||
Cocos2dxHelper.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
nativeOnAudioFocusChange(AUDIOFOCUS_GAIN);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static native void nativeOnAudioFocusChange(int focusChange);
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
// Rename package okhttp3 to org.cocos2dx.okhttp3
|
||||
// Github repo: https://github.com/PatriceJiang/okhttp/tree/cocos2dx-rename-3.12.x
|
||||
// and https://github.com/PatriceJiang/okio/tree/cocos2dx-rename-1.15.0
|
||||
import org.cocos2dx.okhttp3.Call;
|
||||
import org.cocos2dx.okhttp3.Callback;
|
||||
import org.cocos2dx.okhttp3.OkHttpClient;
|
||||
import org.cocos2dx.okhttp3.Request;
|
||||
import org.cocos2dx.okhttp3.Response;
|
||||
|
||||
public class Cocos2dxDownloader {
|
||||
|
||||
private int _id;
|
||||
private OkHttpClient _httpClient = null;
|
||||
|
||||
private String _tempFileNameSuffix;
|
||||
private int _countOfMaxProcessingTasks;
|
||||
private ConcurrentHashMap<Integer,Call> _taskMap = new ConcurrentHashMap<>();
|
||||
private Queue<Runnable> _taskQueue = new LinkedList<>();
|
||||
private int _runningTaskCount = 0;
|
||||
private static ConcurrentHashMap<String, Boolean> _resumingSupport = new ConcurrentHashMap<>();
|
||||
|
||||
private void onProgress(final int id, final long downloadBytes, final long downloadNow, final long downloadTotal) {
|
||||
Cocos2dxHelper.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
nativeOnProgress(_id, id, downloadBytes, downloadNow, downloadTotal);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onFinish(final int id, final int errCode, final String errStr, final byte[] data) {
|
||||
Call task =_taskMap.get(id);
|
||||
if (null == task) return;
|
||||
_taskMap.remove(id);
|
||||
_runningTaskCount -= 1;
|
||||
Cocos2dxHelper.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
nativeOnFinish(_id, id, errCode, errStr, data);
|
||||
}
|
||||
});
|
||||
runNextTaskIfExists();
|
||||
}
|
||||
|
||||
public static Cocos2dxDownloader createDownloader(int id, int timeoutInSeconds, String tempFileSuffix, int maxProcessingTasks) {
|
||||
Cocos2dxDownloader downloader = new Cocos2dxDownloader();
|
||||
downloader._id = id;
|
||||
|
||||
if (timeoutInSeconds > 0) {
|
||||
downloader._httpClient = new OkHttpClient().newBuilder()
|
||||
.followRedirects(true)
|
||||
.followSslRedirects(true)
|
||||
.callTimeout(timeoutInSeconds, TimeUnit.SECONDS)
|
||||
.build();
|
||||
} else {
|
||||
downloader._httpClient = new OkHttpClient().newBuilder()
|
||||
.followRedirects(true)
|
||||
.followSslRedirects(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
downloader._tempFileNameSuffix = tempFileSuffix;
|
||||
downloader._countOfMaxProcessingTasks = maxProcessingTasks;
|
||||
return downloader;
|
||||
}
|
||||
|
||||
public static void createTask(final Cocos2dxDownloader downloader, int id_, String url_, String path_, String []header_) {
|
||||
final int id = id_;
|
||||
final String url = url_;
|
||||
final String path = path_;
|
||||
final String[] header = header_;
|
||||
|
||||
Runnable taskRunnable = new Runnable() {
|
||||
String domain = null;
|
||||
String host = null;
|
||||
File tempFile = null;
|
||||
File finalFile = null;
|
||||
long downloadStart = 0;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Call task = null;
|
||||
|
||||
do {
|
||||
if (path.length() > 0) {
|
||||
try {
|
||||
URI uri = new URI(url);
|
||||
domain = uri.getHost();
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
break;
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
break;
|
||||
}
|
||||
|
||||
// file task
|
||||
tempFile = new File(path + downloader._tempFileNameSuffix);
|
||||
if (tempFile.isDirectory()) break;
|
||||
|
||||
File parent = tempFile.getParentFile();
|
||||
if (!parent.isDirectory() && !parent.mkdirs()) break;
|
||||
|
||||
finalFile = new File(path);
|
||||
if (finalFile.isDirectory()) break;
|
||||
long fileLen = tempFile.length();
|
||||
|
||||
host = domain.startsWith("www.") ? domain.substring(4) : domain;
|
||||
if (fileLen > 0) {
|
||||
if (_resumingSupport.containsKey(host) && _resumingSupport.get(host)) {
|
||||
downloadStart = fileLen;
|
||||
} else {
|
||||
// Remove previous downloaded context
|
||||
try {
|
||||
PrintWriter writer = new PrintWriter(tempFile);
|
||||
writer.print("");
|
||||
writer.close();
|
||||
}
|
||||
// Not found then nothing to do
|
||||
catch (FileNotFoundException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Request.Builder builder = new Request.Builder().url(url);
|
||||
for (int i = 0; i < header.length / 2; i++) {
|
||||
builder.addHeader(header[i * 2], header[(i * 2) + 1]);
|
||||
}
|
||||
if (downloadStart > 0) {
|
||||
builder.addHeader("RANGE", "bytes=" + downloadStart + "-");
|
||||
}
|
||||
|
||||
final Request request = builder.build();
|
||||
task = downloader._httpClient.newCall(request);
|
||||
if (null == task) {
|
||||
final String errStr = "Can't create DownloadTask for " + url;
|
||||
Cocos2dxHelper.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
downloader.nativeOnFinish(downloader._id, id, 0, errStr, null);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
downloader._taskMap.put(id, task);
|
||||
}
|
||||
task.enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
downloader.onFinish(id, 0, e.toString(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException {
|
||||
InputStream is = null;
|
||||
byte[] buf = new byte[4096];
|
||||
FileOutputStream fos = null;
|
||||
|
||||
try {
|
||||
|
||||
if(!(response.code() >= 200 && response.code() <= 206)) {
|
||||
// it is encourage to delete the tmp file when requested range not satisfiable.
|
||||
if (response.code() == 416) {
|
||||
File file = new File(path + downloader._tempFileNameSuffix);
|
||||
if (file.exists() && file.isFile()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
downloader.onFinish(id, -2, response.message(), null);
|
||||
return;
|
||||
}
|
||||
|
||||
long total = response.body().contentLength();
|
||||
if (path.length() > 0 && !_resumingSupport.containsKey(host)) {
|
||||
if (total > 0) {
|
||||
_resumingSupport.put(host, true);
|
||||
} else {
|
||||
_resumingSupport.put(host, false);
|
||||
}
|
||||
}
|
||||
|
||||
long current = downloadStart;
|
||||
is = response.body().byteStream();
|
||||
|
||||
if (path.length() > 0) {
|
||||
if (downloadStart > 0) {
|
||||
fos = new FileOutputStream(tempFile, true);
|
||||
} else {
|
||||
fos = new FileOutputStream(tempFile, false);
|
||||
}
|
||||
|
||||
int len;
|
||||
while ((len = is.read(buf)) != -1) {
|
||||
current += len;
|
||||
fos.write(buf, 0, len);
|
||||
downloader.onProgress(id, len, current, total);
|
||||
}
|
||||
fos.flush();
|
||||
|
||||
String errStr = null;
|
||||
do {
|
||||
// rename temp file to final file, if final file exist, remove it
|
||||
if (finalFile.exists()) {
|
||||
if (finalFile.isDirectory()) {
|
||||
break;
|
||||
}
|
||||
if (!finalFile.delete()) {
|
||||
errStr = "Can't remove old file:" + finalFile.getAbsolutePath();
|
||||
break;
|
||||
}
|
||||
}
|
||||
tempFile.renameTo(finalFile);
|
||||
} while (false);
|
||||
|
||||
if (errStr == null) {
|
||||
downloader.onFinish(id, 0, null, null);
|
||||
downloader.runNextTaskIfExists();
|
||||
}
|
||||
else
|
||||
downloader.onFinish(id, 0, errStr, null);
|
||||
} else {
|
||||
// 非文件
|
||||
ByteArrayOutputStream buffer;
|
||||
if(total > 0) {
|
||||
buffer = new ByteArrayOutputStream((int) total);
|
||||
} else {
|
||||
buffer = new ByteArrayOutputStream(4096);
|
||||
}
|
||||
|
||||
int len;
|
||||
while ((len = is.read(buf)) != -1) {
|
||||
current += len;
|
||||
buffer.write(buf, 0, len);
|
||||
downloader.onProgress(id, len, current, total);
|
||||
}
|
||||
downloader.onFinish(id, 0, null, buffer.toByteArray());
|
||||
downloader.runNextTaskIfExists();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
downloader.onFinish(id, 0, e.toString(), null);
|
||||
} finally {
|
||||
try {
|
||||
if (is != null) {
|
||||
is.close();
|
||||
}
|
||||
if (fos != null) {
|
||||
fos.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e("Cocos2dxDownloader", e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} while (false);
|
||||
}
|
||||
};
|
||||
downloader.enqueueTask(taskRunnable);
|
||||
}
|
||||
|
||||
public static void abort(final Cocos2dxDownloader downloader, final int id) {
|
||||
Cocos2dxHelper.getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Iterator iter = downloader._taskMap.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Map.Entry entry = (Map.Entry) iter.next();
|
||||
Object key = entry.getKey();
|
||||
Call task = (Call) entry.getValue();
|
||||
if (null != task && Integer.parseInt(key.toString()) == id) {
|
||||
task.cancel();
|
||||
downloader._taskMap.remove(id);
|
||||
downloader.runNextTaskIfExists();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void cancelAllRequests(final Cocos2dxDownloader downloader) {
|
||||
Cocos2dxHelper.getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (Object o : downloader._taskMap.entrySet()) {
|
||||
Map.Entry entry = (Map.Entry) o;
|
||||
Call task = (Call) entry.getValue();
|
||||
if (null != task) {
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void enqueueTask(Runnable taskRunnable) {
|
||||
synchronized (_taskQueue) {
|
||||
if (_runningTaskCount < _countOfMaxProcessingTasks) {
|
||||
Cocos2dxHelper.getActivity().runOnUiThread(taskRunnable);
|
||||
_runningTaskCount++;
|
||||
} else {
|
||||
_taskQueue.add(taskRunnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void runNextTaskIfExists() {
|
||||
synchronized (_taskQueue) {
|
||||
while (_runningTaskCount < _countOfMaxProcessingTasks &&
|
||||
Cocos2dxDownloader.this._taskQueue.size() > 0) {
|
||||
|
||||
Runnable taskRunnable = Cocos2dxDownloader.this._taskQueue.poll();
|
||||
Cocos2dxHelper.getActivity().runOnUiThread(taskRunnable);
|
||||
_runningTaskCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
native void nativeOnProgress(int id, int taskId, long dl, long dlnow, long dltotal);
|
||||
native void nativeOnFinish(int id, int taskId, int errCode, String errStr, final byte[] data);
|
||||
}
|
||||
@@ -0,0 +1,479 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.text.Editable;
|
||||
import android.text.InputFilter;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class Cocos2dxEditBox {
|
||||
|
||||
// a color of dark green, was used for confirm button background
|
||||
private static final int DARK_GREEN = Color.parseColor("#1fa014");
|
||||
private static final int DARK_GREEN_PRESS = Color.parseColor("#008e26");
|
||||
|
||||
private static Cocos2dxEditBox sThis = null;
|
||||
private Cocos2dxEditText mEditText = null;
|
||||
private Button mButton = null;
|
||||
private String mButtonTitle = null;
|
||||
private boolean mConfirmHold = true;
|
||||
private Cocos2dxActivity mActivity = null;
|
||||
private RelativeLayout mButtonLayout = null;
|
||||
private RelativeLayout.LayoutParams mButtonParams;
|
||||
private int mEditTextID = 1;
|
||||
private int mButtonLayoutID = 2;
|
||||
|
||||
/***************************************************************************************
|
||||
Inner class.
|
||||
**************************************************************************************/
|
||||
class Cocos2dxEditText extends EditText {
|
||||
private final String TAG = "Cocos2dxEditBox";
|
||||
private boolean mIsMultiLine = false;
|
||||
private TextWatcher mTextWatcher = null;
|
||||
private Paint mPaint;
|
||||
private int mLineColor = DARK_GREEN;
|
||||
private float mLineWidth = 2f;
|
||||
private boolean keyboardVisible = false;
|
||||
private int mScreenHeight;
|
||||
private int mTopMargin = 0;
|
||||
private int mOrientation;
|
||||
|
||||
public Cocos2dxEditText(Cocos2dxActivity context){
|
||||
super(context);
|
||||
//remove focus border
|
||||
this.setBackground(null);
|
||||
this.setTextColor(Color.BLACK);
|
||||
mScreenHeight = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).
|
||||
getDefaultDisplay().getHeight();
|
||||
mPaint = new Paint();
|
||||
mPaint.setStrokeWidth(mLineWidth);
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mPaint.setColor(mLineColor);
|
||||
mOrientation = this.getResources().getConfiguration().orientation;
|
||||
|
||||
mTextWatcher = new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
// Pass text to c++.
|
||||
Cocos2dxEditBox.this.onKeyboardInput(s.toString());
|
||||
}
|
||||
};
|
||||
registKeyboardVisible();
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
Override functions.
|
||||
**************************************************************************************/
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
// draw the underline
|
||||
int padB = this.getPaddingBottom();
|
||||
canvas.drawLine(getScrollX(), this.getHeight() - padB / 2 - mLineWidth,
|
||||
getScrollX() + this.getWidth(),
|
||||
this.getHeight() - padB / 2 - mLineWidth, mPaint);
|
||||
super.onDraw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
int newOrientation = newConfig.orientation;
|
||||
if (mOrientation != newOrientation) {
|
||||
mOrientation = newOrientation;
|
||||
mTopMargin = 0; // clear top margin cache
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
Public functions.
|
||||
**************************************************************************************/
|
||||
|
||||
public void show(String defaultValue, int maxLength, boolean isMultiline, boolean confirmHold, String confirmType, String inputType) {
|
||||
mIsMultiLine = isMultiline;
|
||||
this.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength) });
|
||||
this.setText(defaultValue);
|
||||
if (this.getText().length() >= defaultValue.length()) {
|
||||
this.setSelection(defaultValue.length());
|
||||
} else {
|
||||
this.setSelection(this.getText().length());
|
||||
}
|
||||
this.setConfirmType(confirmType);
|
||||
this.setInputType(inputType, mIsMultiLine);
|
||||
this.setVisibility(View.VISIBLE);
|
||||
|
||||
// Open soft keyboard manually. Should request focus to open soft keyboard.
|
||||
this.requestFocus();
|
||||
|
||||
this.addListeners();
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
mEditText.setVisibility(View.INVISIBLE);
|
||||
this.removeListeners();
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
Private functions.
|
||||
**************************************************************************************/
|
||||
|
||||
private void setConfirmType(final String confirmType) {
|
||||
if (confirmType.contentEquals("done")) {
|
||||
this.setImeOptions(EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
|
||||
mButtonTitle = mActivity.getResources().getString(R.string.done);
|
||||
} else if (confirmType.contentEquals("next")) {
|
||||
this.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
|
||||
mButtonTitle = mActivity.getResources().getString(R.string.next);
|
||||
} else if (confirmType.contentEquals("search")) {
|
||||
this.setImeOptions(EditorInfo.IME_ACTION_SEARCH | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
|
||||
mButtonTitle = mActivity.getResources().getString(R.string.search);
|
||||
} else if (confirmType.contentEquals("go")) {
|
||||
this.setImeOptions(EditorInfo.IME_ACTION_GO | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
|
||||
mButtonTitle = mActivity.getResources().getString(R.string.go);
|
||||
} else if (confirmType.contentEquals("send")) {
|
||||
this.setImeOptions(EditorInfo.IME_ACTION_SEND | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
|
||||
mButtonTitle = mActivity.getResources().getString(R.string.send);
|
||||
} else{
|
||||
mButtonTitle = null;
|
||||
Log.e(TAG, "unknown confirm type " + confirmType);
|
||||
}
|
||||
}
|
||||
|
||||
private void setInputType(final String inputType, boolean isMultiLine){
|
||||
if (inputType.contentEquals("text")) {
|
||||
if (isMultiLine)
|
||||
this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
|
||||
else
|
||||
this.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
}
|
||||
else if (inputType.contentEquals("email"))
|
||||
this.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
|
||||
else if (inputType.contentEquals("number"))
|
||||
this.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL | InputType.TYPE_NUMBER_FLAG_SIGNED);
|
||||
else if (inputType.contentEquals("phone"))
|
||||
this.setInputType(InputType.TYPE_CLASS_PHONE);
|
||||
else if (inputType.contentEquals("password"))
|
||||
this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
else
|
||||
Log.e(TAG, "unknown input type " + inputType);
|
||||
}
|
||||
|
||||
private void addListeners() {
|
||||
|
||||
this.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (! mIsMultiLine) {
|
||||
Cocos2dxEditBox.this.hide();
|
||||
}
|
||||
|
||||
return false; // pass on to other listeners.
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.addTextChangedListener(mTextWatcher);
|
||||
}
|
||||
|
||||
private void removeListeners() {
|
||||
this.setOnEditorActionListener(null);
|
||||
this.removeTextChangedListener(mTextWatcher);
|
||||
}
|
||||
|
||||
private void registKeyboardVisible() {
|
||||
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
Rect r = new Rect();
|
||||
getWindowVisibleDisplayFrame(r);
|
||||
int heightDiff = getRootView().getHeight() - (r.bottom - r.top);
|
||||
// if more than a quarter of the screen, its probably a keyboard
|
||||
if (heightDiff > mScreenHeight/4) {
|
||||
if (!keyboardVisible) {
|
||||
keyboardVisible = true;
|
||||
}
|
||||
} else {
|
||||
if (keyboardVisible) {
|
||||
keyboardVisible = false;
|
||||
Cocos2dxEditBox.this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
if (Cocos2dxEditText.this.mTopMargin == 0 && r.bottom != getRootView().getHeight()) {
|
||||
Cocos2dxEditText.this.setTopMargin(r.bottom);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setTopMargin(int topMargin) {
|
||||
mTopMargin = topMargin;
|
||||
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mEditText.getLayoutParams();
|
||||
layoutParams.topMargin = mTopMargin - getHeight();
|
||||
setLayoutParams(layoutParams);
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public Cocos2dxEditBox(Cocos2dxActivity context, FrameLayout layout) {
|
||||
Cocos2dxEditBox.sThis = this;
|
||||
mActivity = context;
|
||||
this.addItems(context, layout);
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
Public functions.
|
||||
**************************************************************************************/
|
||||
|
||||
// Invoked by surface view to send a complete message to CPP.
|
||||
public static void complete() {
|
||||
Cocos2dxEditBox.sThis.hide();
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
Private functions.
|
||||
**************************************************************************************/
|
||||
private void addItems(Cocos2dxActivity context, FrameLayout layout) {
|
||||
RelativeLayout myLayout = new RelativeLayout(context);
|
||||
myLayout.setFitsSystemWindows(true);
|
||||
this.addEditText(context, myLayout);
|
||||
this.addButton(context, myLayout);
|
||||
|
||||
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
|
||||
layout.addView(myLayout, layoutParams);
|
||||
|
||||
//FXI ME: Is it needed?
|
||||
// When touch area outside EditText and soft keyboard, then hide.
|
||||
// layout.setOnTouchListener(new View.OnTouchListener() {
|
||||
// @Override
|
||||
// public boolean onTouch(View v, MotionEvent event) {
|
||||
// Cocos2dxEditBox.this.hide();
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// });
|
||||
}
|
||||
|
||||
private void addEditText(Cocos2dxActivity context, RelativeLayout layout) {
|
||||
mEditText = new Cocos2dxEditText(context);
|
||||
mEditText.setVisibility(View.INVISIBLE);
|
||||
mEditText.setBackgroundColor(Color.WHITE);
|
||||
mEditText.setId(mEditTextID);
|
||||
RelativeLayout.LayoutParams editParams = new RelativeLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
editParams.addRule(RelativeLayout.LEFT_OF, mButtonLayoutID);
|
||||
layout.addView(mEditText, editParams);
|
||||
}
|
||||
|
||||
private void addButton(Cocos2dxActivity context, RelativeLayout layout) {
|
||||
mButton = new Button(context);
|
||||
mButtonParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
mButton.setTextColor(Color.WHITE);
|
||||
mButton.setBackground(getRoundRectShape());
|
||||
mButtonLayout = new RelativeLayout(Cocos2dxHelper.getActivity());
|
||||
mButtonLayout.setVisibility(View.INVISIBLE);
|
||||
mButtonLayout.setBackgroundColor(Color.WHITE);
|
||||
RelativeLayout.LayoutParams buttonLayoutParams = new RelativeLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
buttonLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
|
||||
buttonLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, mEditTextID);
|
||||
buttonLayoutParams.addRule(RelativeLayout.ALIGN_TOP, mEditTextID);
|
||||
mButtonLayout.addView(mButton, mButtonParams);
|
||||
mButtonLayout.setId(mButtonLayoutID);
|
||||
layout.addView(mButtonLayout, buttonLayoutParams);
|
||||
|
||||
mButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Cocos2dxEditBox.this.onKeyboardConfirm(mEditText.getText().toString());
|
||||
|
||||
if (!Cocos2dxEditBox.this.mConfirmHold)
|
||||
Cocos2dxEditBox.this.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Drawable getRoundRectShape() {
|
||||
int radius = 7;
|
||||
float[] outerRadii = new float[]{radius, radius, radius, radius, radius, radius, radius, radius};
|
||||
RoundRectShape roundRectShape = new RoundRectShape(outerRadii, null, null);
|
||||
ShapeDrawable shapeDrawableNormal = new ShapeDrawable();
|
||||
shapeDrawableNormal.setShape(roundRectShape);
|
||||
shapeDrawableNormal.getPaint().setStyle(Paint.Style.FILL);
|
||||
shapeDrawableNormal.getPaint().setColor(DARK_GREEN);
|
||||
ShapeDrawable shapeDrawablePress = new ShapeDrawable();
|
||||
shapeDrawablePress.setShape(roundRectShape);
|
||||
shapeDrawablePress.getPaint().setStyle(Paint.Style.FILL);
|
||||
shapeDrawablePress.getPaint().setColor(DARK_GREEN_PRESS);
|
||||
StateListDrawable drawable = new StateListDrawable();
|
||||
drawable.addState(new int[]{android.R.attr.state_pressed}, shapeDrawablePress);
|
||||
drawable.addState(new int[]{}, shapeDrawableNormal);
|
||||
return drawable;
|
||||
}
|
||||
|
||||
|
||||
private void hide() {
|
||||
Utils.hideVirtualButton();
|
||||
mEditText.hide();
|
||||
mButtonLayout.setVisibility(View.INVISIBLE);
|
||||
this.closeKeyboard();
|
||||
|
||||
mActivity.getGLSurfaceView().requestFocus();
|
||||
mActivity.getGLSurfaceView().setStopHandleTouchAndKeyEvents(false);
|
||||
}
|
||||
|
||||
private void show(String defaultValue, int maxLength, boolean isMultiline, boolean confirmHold, String confirmType, String inputType) {
|
||||
mConfirmHold = confirmHold;
|
||||
mEditText.show(defaultValue, maxLength, isMultiline, confirmHold, confirmType, inputType);
|
||||
int editPaddingBottom = mEditText.getPaddingBottom();
|
||||
int editPadding = mEditText.getPaddingTop();
|
||||
mEditText.setPadding(editPadding, editPadding, editPadding, editPaddingBottom);
|
||||
mButton.setText(mButtonTitle);
|
||||
if (TextUtils.isEmpty(mButtonTitle)) {
|
||||
mButton.setPadding(0, 0, 0, 0);
|
||||
mButtonParams.setMargins(0, 0, 0, 0);
|
||||
mButtonLayout.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
int buttonTextPadding = mEditText.getPaddingBottom() / 2;
|
||||
mButton.setPadding(editPadding, buttonTextPadding, editPadding, buttonTextPadding);
|
||||
mButtonParams.setMargins(0, buttonTextPadding, 2, 0);
|
||||
mButtonLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
mActivity.getGLSurfaceView().setStopHandleTouchAndKeyEvents(true);
|
||||
this.openKeyboard();
|
||||
}
|
||||
|
||||
private void closeKeyboard() {
|
||||
InputMethodManager imm = (InputMethodManager) Cocos2dxEditBox.this.mActivity.getSystemService(Cocos2dxEditBox.this.mActivity.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
|
||||
|
||||
this.onKeyboardComplete(mEditText.getText().toString());
|
||||
}
|
||||
|
||||
private void openKeyboard() {
|
||||
InputMethodManager imm = (InputMethodManager) Cocos2dxEditBox.this.mActivity.getSystemService(Cocos2dxEditBox.this.mActivity.INPUT_METHOD_SERVICE);
|
||||
imm.showSoftInput(mEditText, InputMethodManager.SHOW_IMPLICIT);
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
Functions invoked by CPP.
|
||||
**************************************************************************************/
|
||||
|
||||
private static void showNative(String defaultValue, int maxLength, boolean isMultiline, boolean confirmHold, String confirmType, String inputType) {
|
||||
if (null != Cocos2dxEditBox.sThis) {
|
||||
Cocos2dxEditBox.sThis.mActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxEditBox.sThis.show(defaultValue, maxLength, isMultiline, confirmHold, confirmType, inputType);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void hideNative() {
|
||||
if (null != Cocos2dxEditBox.sThis) {
|
||||
Cocos2dxEditBox.sThis.mActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxEditBox.sThis.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
Native functions invoked by UI.
|
||||
**************************************************************************************/
|
||||
private void onKeyboardInput(String text) {
|
||||
mActivity.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxEditBox.onKeyboardInputNative(text);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onKeyboardComplete(String text) {
|
||||
mActivity.getGLSurfaceView().requestFocus();
|
||||
mActivity.getGLSurfaceView().setStopHandleTouchAndKeyEvents(false);
|
||||
mActivity.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxEditBox.onKeyboardCompleteNative(text);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onKeyboardConfirm(String text) {
|
||||
mActivity.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxEditBox.onKeyboardConfirmNative(text);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static native void onKeyboardInputNative(String text);
|
||||
private static native void onKeyboardCompleteNative(String text);
|
||||
private static native void onKeyboardConfirmNative(String text);
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2013 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.os.Handler;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class Cocos2dxGLSurfaceView extends GLSurfaceView {
|
||||
// ===========================================================
|
||||
// Constants
|
||||
// ===========================================================
|
||||
|
||||
private static final String TAG = Cocos2dxGLSurfaceView.class.getSimpleName();
|
||||
|
||||
private final static int HANDLER_OPEN_IME_KEYBOARD = 2;
|
||||
private final static int HANDLER_CLOSE_IME_KEYBOARD = 3;
|
||||
|
||||
// ===========================================================
|
||||
// Fields
|
||||
// ===========================================================
|
||||
|
||||
// REFINE: Static handler -> Potential leak!
|
||||
private static Handler sHandler;
|
||||
private static Cocos2dxGLSurfaceView mCocos2dxGLSurfaceView;
|
||||
|
||||
private Cocos2dxRenderer mCocos2dxRenderer;
|
||||
private boolean mStopHandleTouchAndKeyEvents = false;
|
||||
|
||||
public static native void nativeOnSizeChanged(int width, int height);
|
||||
|
||||
// ===========================================================
|
||||
// Constructors
|
||||
// ===========================================================
|
||||
|
||||
public Cocos2dxGLSurfaceView(final Context context) {
|
||||
super(context);
|
||||
|
||||
this.initView();
|
||||
}
|
||||
|
||||
public Cocos2dxGLSurfaceView(final Context context, final AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
this.initView();
|
||||
}
|
||||
|
||||
protected void initView() {
|
||||
this.setEGLContextClientVersion(2);
|
||||
this.setFocusableInTouchMode(true);
|
||||
|
||||
Cocos2dxGLSurfaceView.mCocos2dxGLSurfaceView = this;
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Getter & Setter
|
||||
// ===========================================================
|
||||
|
||||
|
||||
public static Cocos2dxGLSurfaceView getInstance() {
|
||||
return mCocos2dxGLSurfaceView;
|
||||
}
|
||||
|
||||
public static void queueAccelerometer(final float x, final float y, final float z, final long timestamp) {
|
||||
mCocos2dxGLSurfaceView.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxAccelerometer.onSensorChanged(x, y, z, timestamp);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setCocos2dxRenderer(final Cocos2dxRenderer renderer) {
|
||||
this.mCocos2dxRenderer = renderer;
|
||||
this.setRenderer(this.mCocos2dxRenderer);
|
||||
}
|
||||
|
||||
private String getContentText() {
|
||||
return this.mCocos2dxRenderer.getContentText();
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Methods for/from SuperClass/Interfaces
|
||||
// ===========================================================
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
this.setRenderMode(RENDERMODE_CONTINUOUSLY);
|
||||
this.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleOnResume();
|
||||
}
|
||||
});
|
||||
mCocos2dxRenderer.setPauseInMainThread(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
this.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleOnPause();
|
||||
}
|
||||
});
|
||||
this.setRenderMode(RENDERMODE_WHEN_DIRTY);
|
||||
mCocos2dxRenderer.setPauseInMainThread(true);
|
||||
//super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(final MotionEvent pMotionEvent) {
|
||||
// these data are used in ACTION_MOVE and ACTION_CANCEL
|
||||
final int pointerNumber = pMotionEvent.getPointerCount();
|
||||
final int[] ids = new int[pointerNumber];
|
||||
final float[] xs = new float[pointerNumber];
|
||||
final float[] ys = new float[pointerNumber];
|
||||
|
||||
for (int i = 0; i < pointerNumber; i++) {
|
||||
ids[i] = pMotionEvent.getPointerId(i);
|
||||
xs[i] = pMotionEvent.getX(i);
|
||||
ys[i] = pMotionEvent.getY(i);
|
||||
}
|
||||
|
||||
switch (pMotionEvent.getAction() & MotionEvent.ACTION_MASK) {
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
if (mStopHandleTouchAndKeyEvents) {
|
||||
Cocos2dxEditBox.complete();
|
||||
return true;
|
||||
}
|
||||
|
||||
final int indexPointerDown = pMotionEvent.getAction() >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
|
||||
final int idPointerDown = pMotionEvent.getPointerId(indexPointerDown);
|
||||
final float xPointerDown = pMotionEvent.getX(indexPointerDown);
|
||||
final float yPointerDown = pMotionEvent.getY(indexPointerDown);
|
||||
|
||||
this.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown(idPointerDown, xPointerDown, yPointerDown);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if (mStopHandleTouchAndKeyEvents) {
|
||||
Cocos2dxEditBox.complete();
|
||||
return true;
|
||||
}
|
||||
|
||||
// there are only one finger on the screen
|
||||
final int idDown = pMotionEvent.getPointerId(0);
|
||||
final float xDown = xs[0];
|
||||
final float yDown = ys[0];
|
||||
|
||||
this.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown(idDown, xDown, yDown);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
this.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionMove(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
final int indexPointUp = pMotionEvent.getAction() >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
|
||||
final int idPointerUp = pMotionEvent.getPointerId(indexPointUp);
|
||||
final float xPointerUp = pMotionEvent.getX(indexPointUp);
|
||||
final float yPointerUp = pMotionEvent.getY(indexPointUp);
|
||||
|
||||
this.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionUp(idPointerUp, xPointerUp, yPointerUp);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
// there are only one finger on the screen
|
||||
final int idUp = pMotionEvent.getPointerId(0);
|
||||
final float xUp = xs[0];
|
||||
final float yUp = ys[0];
|
||||
|
||||
this.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionUp(idUp, xUp, yUp);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
this.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionCancel(ids, xs, ys);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
if (BuildConfig.DEBUG) {
|
||||
Cocos2dxGLSurfaceView.dumpMotionEvent(pMotionEvent);
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called before Cocos2dxRenderer.nativeInit(), so the
|
||||
* width and height is correct.
|
||||
*/
|
||||
@Override
|
||||
protected void onSizeChanged(final int pNewSurfaceWidth, final int pNewSurfaceHeight, final int pOldSurfaceWidth, final int pOldSurfaceHeight) {
|
||||
if(!this.isInEditMode()) {
|
||||
this.mCocos2dxRenderer.setScreenWidthAndHeight(pNewSurfaceWidth, pNewSurfaceHeight);
|
||||
nativeOnSizeChanged(pNewSurfaceWidth, pNewSurfaceHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(final int pKeyCode, final KeyEvent pKeyEvent) {
|
||||
switch (pKeyCode) {
|
||||
case KeyEvent.KEYCODE_BACK:
|
||||
Cocos2dxVideoHelper.mVideoHandler.sendEmptyMessage(Cocos2dxVideoHelper.KeyEventBack);
|
||||
case KeyEvent.KEYCODE_MENU:
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
case KeyEvent.KEYCODE_ENTER:
|
||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case KeyEvent.KEYCODE_DPAD_CENTER:
|
||||
this.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleKeyDown(pKeyCode);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
default:
|
||||
return super.onKeyDown(pKeyCode, pKeyEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(final int keyCode, KeyEvent event) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_BACK:
|
||||
case KeyEvent.KEYCODE_MENU:
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
case KeyEvent.KEYCODE_ENTER:
|
||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case KeyEvent.KEYCODE_DPAD_CENTER:
|
||||
this.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleKeyUp(keyCode);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
default:
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Methods
|
||||
// ===========================================================
|
||||
|
||||
public void setStopHandleTouchAndKeyEvents(boolean value) {
|
||||
mStopHandleTouchAndKeyEvents = value;
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Inner and Anonymous Classes
|
||||
// ===========================================================
|
||||
|
||||
private static void dumpMotionEvent(final MotionEvent event) {
|
||||
final String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE", "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final int action = event.getAction();
|
||||
final int actionCode = action & MotionEvent.ACTION_MASK;
|
||||
sb.append("event ACTION_").append(names[actionCode]);
|
||||
if (actionCode == MotionEvent.ACTION_POINTER_DOWN || actionCode == MotionEvent.ACTION_POINTER_UP) {
|
||||
sb.append("(pid ").append(action >> MotionEvent.ACTION_POINTER_INDEX_SHIFT);
|
||||
sb.append(")");
|
||||
}
|
||||
sb.append("[");
|
||||
for (int i = 0; i < event.getPointerCount(); i++) {
|
||||
sb.append("#").append(i);
|
||||
sb.append("(pid ").append(event.getPointerId(i));
|
||||
sb.append(")=").append((int) event.getX(i));
|
||||
sb.append(",").append((int) event.getY(i));
|
||||
if (i + 1 < event.getPointerCount()) {
|
||||
sb.append(";");
|
||||
}
|
||||
}
|
||||
sb.append("]");
|
||||
Log.d(Cocos2dxGLSurfaceView.TAG, sb.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2013 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class Cocos2dxHandler extends Handler {
|
||||
// ===========================================================
|
||||
// Constants
|
||||
// ===========================================================
|
||||
public final static int HANDLER_SHOW_DIALOG = 1;
|
||||
|
||||
// ===========================================================
|
||||
// Fields
|
||||
// ===========================================================
|
||||
private WeakReference<Cocos2dxActivity> mActivity;
|
||||
|
||||
// ===========================================================
|
||||
// Constructors
|
||||
// ===========================================================
|
||||
public Cocos2dxHandler(Cocos2dxActivity activity) {
|
||||
this.mActivity = new WeakReference<Cocos2dxActivity>(activity);
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Getter & Setter
|
||||
// ===========================================================
|
||||
|
||||
// ===========================================================
|
||||
// Methods for/from SuperClass/Interfaces
|
||||
// ===========================================================
|
||||
|
||||
// ===========================================================
|
||||
// Methods
|
||||
// ===========================================================
|
||||
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case Cocos2dxHandler.HANDLER_SHOW_DIALOG:
|
||||
showDialog(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void showDialog(Message msg) {
|
||||
Cocos2dxActivity theActivity = this.mActivity.get();
|
||||
DialogMessage dialogMessage = (DialogMessage)msg.obj;
|
||||
new AlertDialog.Builder(theActivity)
|
||||
.setTitle(dialogMessage.title)
|
||||
.setMessage(dialogMessage.message)
|
||||
.setPositiveButton("Ok",
|
||||
new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// REFINE: Auto-generated method stub
|
||||
|
||||
}
|
||||
}).create().show();
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Inner and Anonymous Classes
|
||||
// ===========================================================
|
||||
|
||||
public static class DialogMessage {
|
||||
public String title;
|
||||
public String message;
|
||||
|
||||
public DialogMessage(String title, String message) {
|
||||
this.title = title;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,664 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.content.res.AssetManager;
|
||||
import android.media.AudioManager;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.Vibrator;
|
||||
import android.preference.PreferenceManager.OnActivityResultListener;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.Surface;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.vending.expansion.zipfile.APKExpansionSupport;
|
||||
import com.android.vending.expansion.zipfile.ZipResourceFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class Cocos2dxHelper {
|
||||
// ===========================================================
|
||||
// Constants
|
||||
// ===========================================================
|
||||
private static final String PREFS_NAME = "Cocos2dxPrefsFile";
|
||||
private static final int RUNNABLES_PER_FRAME = 5;
|
||||
private static final String TAG = Cocos2dxHelper.class.getSimpleName();
|
||||
|
||||
// ===========================================================
|
||||
// Fields
|
||||
// ===========================================================
|
||||
|
||||
private static AssetManager sAssetManager;
|
||||
private static Cocos2dxAccelerometer sCocos2dxAccelerometer;
|
||||
private static boolean sAccelerometerEnabled;
|
||||
private static boolean sCompassEnabled;
|
||||
private static boolean sActivityVisible;
|
||||
private static String sPackageName;
|
||||
private static String sFileDirectory;
|
||||
private static Activity sActivity = null;
|
||||
private static Cocos2dxHelperListener sCocos2dxHelperListener;
|
||||
private static Set<OnActivityResultListener> onActivityResultListeners = new LinkedHashSet<OnActivityResultListener>();
|
||||
private static Vibrator sVibrateService = null;
|
||||
|
||||
// The absolute path to the OBB if it exists, else the absolute path to the APK.
|
||||
private static String sAssetsPath = "";
|
||||
|
||||
// The OBB file
|
||||
private static ZipResourceFile sOBBFile = null;
|
||||
|
||||
/**
|
||||
* Battery receiver to getting battery level.
|
||||
*/
|
||||
static class BatteryReceiver extends BroadcastReceiver {
|
||||
public float sBatteryLevel = 0.0f;
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
setBatteryLevelByIntent(intent);
|
||||
}
|
||||
|
||||
public void setBatteryLevelByIntent(Intent intent) {
|
||||
if (null != intent) {
|
||||
int current = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
|
||||
int total = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);
|
||||
float level = current * 1.0f / total;
|
||||
// clamp to 0~1
|
||||
sBatteryLevel = Math.min(Math.max(level, 0.0f), 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static BatteryReceiver sBatteryReceiver = new BatteryReceiver();
|
||||
|
||||
static void registerBatteryLevelReceiver(Context context) {
|
||||
Intent intent = context.registerReceiver(sBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
sBatteryReceiver.setBatteryLevelByIntent(intent);
|
||||
}
|
||||
|
||||
static void unregisterBatteryLevelReceiver(Context context) {
|
||||
context.unregisterReceiver(sBatteryReceiver);
|
||||
}
|
||||
|
||||
public static float getBatteryLevel() {
|
||||
return sBatteryReceiver.sBatteryLevel;
|
||||
}
|
||||
|
||||
public static final int NETWORK_TYPE_NONE = 0;
|
||||
public static final int NETWORK_TYPE_LAN = 1;
|
||||
public static final int NETWORK_TYPE_WWAN = 2;
|
||||
|
||||
public static int getNetworkType() {
|
||||
int status = NETWORK_TYPE_NONE;
|
||||
NetworkInfo networkInfo;
|
||||
try {
|
||||
ConnectivityManager connMgr = (ConnectivityManager) sActivity.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
networkInfo = connMgr.getActiveNetworkInfo();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return status;
|
||||
}
|
||||
if (networkInfo == null) {
|
||||
return status;
|
||||
}
|
||||
int nType = networkInfo.getType();
|
||||
if (nType == ConnectivityManager.TYPE_MOBILE) {
|
||||
status = NETWORK_TYPE_WWAN;
|
||||
} else if (nType == ConnectivityManager.TYPE_WIFI) {
|
||||
status = NETWORK_TYPE_LAN;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Constructors
|
||||
// ===========================================================
|
||||
|
||||
public static void runOnGLThread(final Runnable r) {
|
||||
((Cocos2dxActivity)sActivity).runOnGLThread(r);
|
||||
}
|
||||
|
||||
private static boolean sInited = false;
|
||||
public static void init(final Activity activity) {
|
||||
sActivity = activity;
|
||||
Cocos2dxHelper.sCocos2dxHelperListener = (Cocos2dxHelperListener)activity;
|
||||
if (!sInited) {
|
||||
|
||||
PackageManager pm = activity.getPackageManager();
|
||||
boolean isSupportLowLatency = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
|
||||
|
||||
Log.d(TAG, "isSupportLowLatency:" + isSupportLowLatency);
|
||||
|
||||
int sampleRate = 44100;
|
||||
int bufferSizeInFrames = 192;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 17) {
|
||||
AudioManager am = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE);
|
||||
// use reflection to remove dependence of API 17 when compiling
|
||||
|
||||
// AudioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
|
||||
final Class audioManagerClass = AudioManager.class;
|
||||
Object[] parameters = new Object[]{Cocos2dxReflectionHelper.<String>getConstantValue(audioManagerClass, "PROPERTY_OUTPUT_SAMPLE_RATE")};
|
||||
final String strSampleRate = Cocos2dxReflectionHelper.<String>invokeInstanceMethod(am, "getProperty", new Class[]{String.class}, parameters);
|
||||
|
||||
// AudioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
|
||||
parameters = new Object[]{Cocos2dxReflectionHelper.<String>getConstantValue(audioManagerClass, "PROPERTY_OUTPUT_FRAMES_PER_BUFFER")};
|
||||
final String strBufferSizeInFrames = Cocos2dxReflectionHelper.<String>invokeInstanceMethod(am, "getProperty", new Class[]{String.class}, parameters);
|
||||
|
||||
sampleRate = Integer.parseInt(strSampleRate);
|
||||
bufferSizeInFrames = Integer.parseInt(strBufferSizeInFrames);
|
||||
|
||||
Log.d(TAG, "sampleRate: " + sampleRate + ", framesPerBuffer: " + bufferSizeInFrames);
|
||||
} else {
|
||||
Log.d(TAG, "android version is lower than 17");
|
||||
}
|
||||
|
||||
nativeSetAudioDeviceInfo(isSupportLowLatency, sampleRate, bufferSizeInFrames);
|
||||
|
||||
final ApplicationInfo applicationInfo = activity.getApplicationInfo();
|
||||
|
||||
Cocos2dxHelper.sPackageName = applicationInfo.packageName;
|
||||
Cocos2dxHelper.sFileDirectory = activity.getFilesDir().getAbsolutePath();
|
||||
|
||||
Cocos2dxHelper.nativeSetApkPath(Cocos2dxHelper.getAssetsPath());
|
||||
|
||||
Cocos2dxHelper.sCocos2dxAccelerometer = new Cocos2dxAccelerometer(activity);
|
||||
Cocos2dxHelper.sAssetManager = activity.getAssets();
|
||||
Cocos2dxHelper.nativeSetContext((Context)activity, Cocos2dxHelper.sAssetManager);
|
||||
Cocos2dxHelper.sVibrateService = (Vibrator)activity.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
|
||||
sInited = true;
|
||||
|
||||
int versionCode = 1;
|
||||
try {
|
||||
versionCode = Cocos2dxActivity.getContext().getPackageManager().getPackageInfo(Cocos2dxHelper.getPackageName(), 0).versionCode;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
Cocos2dxHelper.sOBBFile = APKExpansionSupport.getAPKExpansionZipFile(Cocos2dxActivity.getContext(), versionCode, 0);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function returns the absolute path to the OBB if it exists,
|
||||
// else it returns the absolute path to the APK.
|
||||
public static String getAssetsPath()
|
||||
{
|
||||
if (Cocos2dxHelper.sAssetsPath == "") {
|
||||
int versionCode = 1;
|
||||
try {
|
||||
versionCode = Cocos2dxHelper.sActivity.getPackageManager().getPackageInfo(Cocos2dxHelper.sPackageName, 0).versionCode;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
String pathToOBB = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/obb/" + Cocos2dxHelper.sPackageName + "/main." + versionCode + "." + Cocos2dxHelper.sPackageName + ".obb";
|
||||
File obbFile = new File(pathToOBB);
|
||||
if (obbFile.exists())
|
||||
Cocos2dxHelper.sAssetsPath = pathToOBB;
|
||||
else
|
||||
Cocos2dxHelper.sAssetsPath = Cocos2dxHelper.sActivity.getApplicationInfo().sourceDir;
|
||||
}
|
||||
|
||||
return Cocos2dxHelper.sAssetsPath;
|
||||
}
|
||||
|
||||
public static ZipResourceFile getObbFile()
|
||||
{
|
||||
return Cocos2dxHelper.sOBBFile;
|
||||
}
|
||||
|
||||
public static Activity getActivity() {
|
||||
return sActivity;
|
||||
}
|
||||
|
||||
public static void addOnActivityResultListener(OnActivityResultListener listener) {
|
||||
onActivityResultListeners.add(listener);
|
||||
}
|
||||
|
||||
public static Set<OnActivityResultListener> getOnActivityResultListeners() {
|
||||
return onActivityResultListeners;
|
||||
}
|
||||
|
||||
public static boolean isActivityVisible(){
|
||||
return sActivityVisible;
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Getter & Setter
|
||||
// ===========================================================
|
||||
|
||||
// ===========================================================
|
||||
// Methods for/from SuperClass/Interfaces
|
||||
// ===========================================================
|
||||
|
||||
// ===========================================================
|
||||
// Methods
|
||||
// ===========================================================
|
||||
|
||||
private static native void nativeSetApkPath(final String pApkPath);
|
||||
|
||||
private static native void nativeSetEditTextDialogResult(final byte[] pBytes);
|
||||
|
||||
private static native void nativeSetContext(final Context pContext, final AssetManager pAssetManager);
|
||||
|
||||
private static native void nativeSetAudioDeviceInfo(boolean isSupportLowLatency, int deviceSampleRate, int audioBufferSizeInFames);
|
||||
|
||||
public static String getPackageName() {
|
||||
return Cocos2dxHelper.sPackageName;
|
||||
}
|
||||
public static String getWritablePath() {
|
||||
return Cocos2dxHelper.sFileDirectory;
|
||||
}
|
||||
|
||||
public static String getCurrentLanguage() {
|
||||
return Locale.getDefault().getLanguage();
|
||||
}
|
||||
|
||||
public static String getCurrentLanguageCode() {
|
||||
return Locale.getDefault().toString();
|
||||
}
|
||||
|
||||
public static String getDeviceModel(){
|
||||
return Build.MODEL;
|
||||
}
|
||||
|
||||
public static AssetManager getAssetManager() {
|
||||
return Cocos2dxHelper.sAssetManager;
|
||||
}
|
||||
|
||||
public static void enableAccelerometer() {
|
||||
Cocos2dxHelper.sAccelerometerEnabled = true;
|
||||
Cocos2dxHelper.sCocos2dxAccelerometer.enable();
|
||||
}
|
||||
|
||||
public static void setAccelerometerInterval(float interval) {
|
||||
Cocos2dxHelper.sCocos2dxAccelerometer.setInterval(interval);
|
||||
}
|
||||
|
||||
public static void disableAccelerometer() {
|
||||
Cocos2dxHelper.sAccelerometerEnabled = false;
|
||||
Cocos2dxHelper.sCocos2dxAccelerometer.disable();
|
||||
}
|
||||
|
||||
public static void setKeepScreenOn(boolean value) {
|
||||
((Cocos2dxActivity)sActivity).setKeepScreenOn(value);
|
||||
}
|
||||
|
||||
public static void vibrate(float duration) {
|
||||
try {
|
||||
if (sVibrateService != null && sVibrateService.hasVibrator()) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= 26) {
|
||||
Class<?> vibrationEffectClass = Class.forName("android.os.VibrationEffect");
|
||||
if(vibrationEffectClass != null) {
|
||||
final int DEFAULT_AMPLITUDE = Cocos2dxReflectionHelper.<Integer>getConstantValue(vibrationEffectClass,
|
||||
"DEFAULT_AMPLITUDE");
|
||||
//VibrationEffect.createOneShot(long milliseconds, int amplitude)
|
||||
final Method method = vibrationEffectClass.getMethod("createOneShot",
|
||||
new Class[]{Long.TYPE, Integer.TYPE});
|
||||
Class<?> type = method.getReturnType();
|
||||
|
||||
Object effect = method.invoke(vibrationEffectClass,
|
||||
new Object[]{(long) (duration * 1000), DEFAULT_AMPLITUDE});
|
||||
//sVibrateService.vibrate(VibrationEffect effect);
|
||||
Cocos2dxReflectionHelper.invokeInstanceMethod(sVibrateService,"vibrate",
|
||||
new Class[]{type}, new Object[]{(effect)});
|
||||
}
|
||||
} else {
|
||||
sVibrateService.vibrate((long) (duration * 1000));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
try {
|
||||
String version = Cocos2dxActivity.getContext().getPackageManager().getPackageInfo(Cocos2dxActivity.getContext().getPackageName(), 0).versionName;
|
||||
return version;
|
||||
} catch(Exception e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean openURL(String url) {
|
||||
boolean ret = false;
|
||||
try {
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
i.setData(Uri.parse(url));
|
||||
sActivity.startActivity(i);
|
||||
ret = true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 复制文本到剪切板
|
||||
public static void copyTextToClipboard(final String text){
|
||||
sActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ClipboardManager myClipboard = (ClipboardManager)sActivity.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData myClip = ClipData.newPlainText("text", text);
|
||||
myClipboard.setPrimaryClip(myClip);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static long[] getObbAssetFileDescriptor(final String path) {
|
||||
long[] array = new long[3];
|
||||
if (Cocos2dxHelper.sOBBFile != null) {
|
||||
AssetFileDescriptor descriptor = Cocos2dxHelper.sOBBFile.getAssetFileDescriptor(path);
|
||||
if (descriptor != null) {
|
||||
try {
|
||||
ParcelFileDescriptor parcel = descriptor.getParcelFileDescriptor();
|
||||
Method method = parcel.getClass().getMethod("getFd", new Class[] {});
|
||||
array[0] = (Integer)method.invoke(parcel);
|
||||
array[1] = descriptor.getStartOffset();
|
||||
array[2] = descriptor.getLength();
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log.e(Cocos2dxHelper.TAG, "Accessing file descriptor directly from the OBB is only supported from Android 3.1 (API level 12) and above.");
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.e(Cocos2dxHelper.TAG, e.toString());
|
||||
} catch (InvocationTargetException e) {
|
||||
Log.e(Cocos2dxHelper.TAG, e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public static void endApplication() {
|
||||
if (sActivity != null)
|
||||
sActivity.finish();
|
||||
}
|
||||
|
||||
public static void onResume() {
|
||||
sActivityVisible = true;
|
||||
if (Cocos2dxHelper.sAccelerometerEnabled) {
|
||||
Cocos2dxHelper.sCocos2dxAccelerometer.enable();
|
||||
}
|
||||
}
|
||||
|
||||
public static void onPause() {
|
||||
sActivityVisible = false;
|
||||
if (Cocos2dxHelper.sAccelerometerEnabled) {
|
||||
Cocos2dxHelper.sCocos2dxAccelerometer.disable();
|
||||
}
|
||||
}
|
||||
|
||||
public static void onEnterBackground() {
|
||||
|
||||
}
|
||||
|
||||
public static void onEnterForeground() {
|
||||
|
||||
}
|
||||
|
||||
public static void terminateProcess() {
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
}
|
||||
|
||||
private static void showDialog(final String pTitle, final String pMessage) {
|
||||
Cocos2dxHelper.sCocos2dxHelperListener.showDialog(pTitle, pMessage);
|
||||
}
|
||||
|
||||
public static void setEditTextDialogResult(final String pResult) {
|
||||
try {
|
||||
final byte[] bytesUTF8 = pResult.getBytes("UTF8");
|
||||
|
||||
Cocos2dxHelper.sCocos2dxHelperListener.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxHelper.nativeSetEditTextDialogResult(bytesUTF8);
|
||||
}
|
||||
});
|
||||
} catch (UnsupportedEncodingException pUnsupportedEncodingException) {
|
||||
/* Nothing. */
|
||||
}
|
||||
}
|
||||
|
||||
private static int displayMetricsToDPI(DisplayMetrics metrics)
|
||||
{
|
||||
if(metrics.xdpi != metrics.ydpi) {
|
||||
Log.w(Cocos2dxHelper.TAG, "xdpi != ydpi, use (xdpi + ydpi)/2 instead.");
|
||||
return (int) ((metrics.xdpi + metrics.ydpi) / 2.0);
|
||||
} else {
|
||||
return (int)metrics.xdpi;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getDPI()
|
||||
{
|
||||
if (sActivity != null)
|
||||
{
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
WindowManager wm = sActivity.getWindowManager();
|
||||
if (wm != null)
|
||||
{
|
||||
Display d = wm.getDefaultDisplay();
|
||||
if (d != null)
|
||||
{
|
||||
try {
|
||||
Method getRealMetrics = d.getClass().getMethod("getRealMetrics", metrics.getClass());
|
||||
getRealMetrics.invoke(d, metrics);
|
||||
return displayMetricsToDPI(metrics);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
d.getMetrics(metrics);
|
||||
return displayMetricsToDPI(metrics);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static byte[] conversionEncoding(byte[] text, String fromCharset,String newCharset)
|
||||
{
|
||||
try {
|
||||
String str = new String(text,fromCharset);
|
||||
return str.getBytes(newCharset);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void setGameInfoDebugViewText(int index, String text) {
|
||||
if (sOnGameInfoUpdatedListener != null) {
|
||||
if (index == 0) {
|
||||
sOnGameInfoUpdatedListener.onGameInfoUpdated_0(text);
|
||||
}
|
||||
else if (index == 1) {
|
||||
sOnGameInfoUpdatedListener.onGameInfoUpdated_1(text);
|
||||
}
|
||||
else if (index == 2) {
|
||||
sOnGameInfoUpdatedListener.onGameInfoUpdated_2(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void setJSBInvocationCount(int count) {
|
||||
if (sOnGameInfoUpdatedListener != null) {
|
||||
sOnGameInfoUpdatedListener.onJSBInvocationCountUpdated(count);
|
||||
}
|
||||
}
|
||||
|
||||
private static void openDebugView() {
|
||||
if (sOnGameInfoUpdatedListener != null) {
|
||||
sOnGameInfoUpdatedListener.onOpenDebugView();
|
||||
}
|
||||
}
|
||||
|
||||
private static void disableBatchGLCommandsToNative() {
|
||||
if (sOnGameInfoUpdatedListener != null) {
|
||||
sOnGameInfoUpdatedListener.onDisableBatchGLCommandsToNative();
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnGameInfoUpdatedListener {
|
||||
void onFPSUpdated(float fps);
|
||||
void onJSBInvocationCountUpdated(int count);
|
||||
void onOpenDebugView();
|
||||
void onDisableBatchGLCommandsToNative();
|
||||
void onGameInfoUpdated_0(String text);
|
||||
void onGameInfoUpdated_1(String text);
|
||||
void onGameInfoUpdated_2(String text);
|
||||
}
|
||||
|
||||
private static OnGameInfoUpdatedListener sOnGameInfoUpdatedListener;
|
||||
|
||||
public static void setOnGameInfoUpdatedListener(OnGameInfoUpdatedListener listener) {
|
||||
sOnGameInfoUpdatedListener = listener;
|
||||
}
|
||||
|
||||
public static OnGameInfoUpdatedListener getOnGameInfoUpdatedListener() {
|
||||
return sOnGameInfoUpdatedListener;
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Inner and Anonymous Classes
|
||||
// ===========================================================
|
||||
|
||||
public static interface Cocos2dxHelperListener {
|
||||
public void showDialog(final String pTitle, final String pMessage);
|
||||
|
||||
public void runOnGLThread(final Runnable pRunnable);
|
||||
}
|
||||
|
||||
private static float[] sDeviceMotionValues = new float[9];
|
||||
|
||||
private static float[] getDeviceMotionValue() {
|
||||
Cocos2dxAccelerometer.DeviceMotionEvent event = Cocos2dxHelper.sCocos2dxAccelerometer.getDeviceMotionEvent();
|
||||
sDeviceMotionValues[0] = event.acceleration.x;
|
||||
sDeviceMotionValues[1] = event.acceleration.y;
|
||||
// Issue https://github.com/cocos-creator/2d-tasks/issues/2532
|
||||
// use negative event.acceleration.z to match iOS value
|
||||
sDeviceMotionValues[2] = - event.acceleration.z;
|
||||
|
||||
sDeviceMotionValues[3] = event.accelerationIncludingGravity.x;
|
||||
sDeviceMotionValues[4] = event.accelerationIncludingGravity.y;
|
||||
sDeviceMotionValues[5] = event.accelerationIncludingGravity.z;
|
||||
|
||||
sDeviceMotionValues[6] = event.rotationRate.alpha;
|
||||
sDeviceMotionValues[7] = event.rotationRate.beta;
|
||||
sDeviceMotionValues[8] = event.rotationRate.gamma;
|
||||
|
||||
return sDeviceMotionValues;
|
||||
}
|
||||
|
||||
public static int getSDKVersion() {
|
||||
return Build.VERSION.SDK_INT;
|
||||
}
|
||||
|
||||
public static String getSystemVersion() {
|
||||
return Build.VERSION.RELEASE;
|
||||
}
|
||||
|
||||
|
||||
public static int getDeviceRotation() {
|
||||
try {
|
||||
Display display = ((WindowManager) sActivity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
||||
return display.getRotation();
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return Surface.ROTATION_0;
|
||||
}
|
||||
|
||||
public static float[] getSafeArea() {
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= 28) {
|
||||
|
||||
do {
|
||||
Object windowInsectObj = getActivity().getWindow().getDecorView().getRootWindowInsets();
|
||||
|
||||
if(windowInsectObj == null) break;
|
||||
|
||||
Class<?> windowInsets = WindowInsets.class;
|
||||
try {
|
||||
Method wiGetDisplayCutout = windowInsets.getMethod("getDisplayCutout");
|
||||
Object cutout = wiGetDisplayCutout.invoke(windowInsectObj);
|
||||
|
||||
if(cutout == null) break;
|
||||
|
||||
Class<?> displayCutout = cutout.getClass();
|
||||
Method dcGetLeft = displayCutout.getMethod("getSafeInsetLeft");
|
||||
Method dcGetRight = displayCutout.getMethod("getSafeInsetRight");
|
||||
Method dcGetBottom = displayCutout.getMethod("getSafeInsetBottom");
|
||||
Method dcGetTop = displayCutout.getMethod("getSafeInsetTop");
|
||||
|
||||
if (dcGetLeft != null && dcGetRight != null && dcGetBottom != null && dcGetTop != null) {
|
||||
int left = (Integer) dcGetLeft.invoke(cutout);
|
||||
int right = (Integer) dcGetRight.invoke(cutout);
|
||||
int top = (Integer) dcGetTop.invoke(cutout);
|
||||
int bottom = (Integer) dcGetBottom.invoke(cutout);
|
||||
return new float[]{top, left, bottom, right};
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}while(false);
|
||||
}
|
||||
return new float[]{0,0,0,0};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,413 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2014 cocos2d-x.org
|
||||
Copyright (c) 2014-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
import java.security.KeyStore;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
public class Cocos2dxHttpURLConnection
|
||||
{
|
||||
private static String TAG = "Cocos2dxHttpURLConnection";
|
||||
private static final String POST_METHOD = "POST" ;
|
||||
private static final String PUT_METHOD = "PUT" ;
|
||||
|
||||
static HttpURLConnection createHttpURLConnection(String linkURL) {
|
||||
URL url;
|
||||
HttpURLConnection urlConnection;
|
||||
try {
|
||||
url = new URL(linkURL);
|
||||
urlConnection = (HttpURLConnection) url.openConnection();
|
||||
//Accept-Encoding
|
||||
urlConnection.setRequestProperty("Accept-Encoding", "identity");
|
||||
urlConnection.setDoInput(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "createHttpURLConnection:" + e.toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
return urlConnection;
|
||||
}
|
||||
|
||||
static void setReadAndConnectTimeout(HttpURLConnection urlConnection, int readMiliseconds, int connectMiliseconds) {
|
||||
urlConnection.setReadTimeout(readMiliseconds);
|
||||
urlConnection.setConnectTimeout(connectMiliseconds);
|
||||
}
|
||||
|
||||
static void setRequestMethod(HttpURLConnection urlConnection, String method){
|
||||
try {
|
||||
urlConnection.setRequestMethod(method);
|
||||
if(method.equalsIgnoreCase(POST_METHOD) || method.equalsIgnoreCase(PUT_METHOD)) {
|
||||
urlConnection.setDoOutput(true);
|
||||
}
|
||||
} catch (ProtocolException e) {
|
||||
Log.e(TAG, "setRequestMethod:" + e.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void setVerifySSL(HttpURLConnection urlConnection, String sslFilename) {
|
||||
if(!(urlConnection instanceof HttpsURLConnection))
|
||||
return;
|
||||
|
||||
|
||||
HttpsURLConnection httpsURLConnection = (HttpsURLConnection)urlConnection;
|
||||
|
||||
try {
|
||||
InputStream caInput = null;
|
||||
if (sslFilename.startsWith("/")) {
|
||||
caInput = new BufferedInputStream(new FileInputStream(sslFilename));
|
||||
}else {
|
||||
String assetString = "assets/";
|
||||
String assetsfilenameString = sslFilename.substring(assetString.length());
|
||||
caInput = new BufferedInputStream(Cocos2dxHelper.getActivity().getAssets().open(assetsfilenameString));
|
||||
}
|
||||
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
Certificate ca;
|
||||
ca = cf.generateCertificate(caInput);
|
||||
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
|
||||
caInput.close();
|
||||
|
||||
// Create a KeyStore containing our trusted CAs
|
||||
String keyStoreType = KeyStore.getDefaultType();
|
||||
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
|
||||
keyStore.load(null, null);
|
||||
keyStore.setCertificateEntry("ca", ca);
|
||||
|
||||
// Create a TrustManager that trusts the CAs in our KeyStore
|
||||
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
|
||||
tmf.init(keyStore);
|
||||
|
||||
// Create an SSLContext that uses our TrustManager
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(null, tmf.getTrustManagers(), null);
|
||||
|
||||
httpsURLConnection.setSSLSocketFactory(context.getSocketFactory());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "setVerifySSL:" + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
//Add header
|
||||
static void addRequestHeader(HttpURLConnection urlConnection, String key, String value) {
|
||||
urlConnection.setRequestProperty(key, value);
|
||||
}
|
||||
|
||||
static int connect(HttpURLConnection http) {
|
||||
int suc = 0;
|
||||
|
||||
try {
|
||||
http.connect();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "connect" + e.toString());
|
||||
suc = 1;
|
||||
}
|
||||
|
||||
return suc;
|
||||
}
|
||||
|
||||
static void disconnect(HttpURLConnection http) {
|
||||
http.disconnect();
|
||||
}
|
||||
|
||||
static void sendRequest(HttpURLConnection http, byte[] byteArray) {
|
||||
try {
|
||||
OutputStream out = http.getOutputStream();
|
||||
if(null != byteArray) {
|
||||
out.write(byteArray);
|
||||
out.flush();
|
||||
}
|
||||
out.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "sendRequest:" + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
static String getResponseHeaders(HttpURLConnection http) {
|
||||
Map<String, List<String>> headers = http.getHeaderFields();
|
||||
if (null == headers) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String header = "";
|
||||
|
||||
for (Entry<String, List<String>> entry: headers.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (null == key) {
|
||||
header += listToString(entry.getValue(), ",") + "\n";
|
||||
} else {
|
||||
header += key + ":" + listToString(entry.getValue(), ",") + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
static String getResponseHeaderByIdx(HttpURLConnection http, int idx) {
|
||||
Map<String, List<String>> headers = http.getHeaderFields();
|
||||
if (null == headers) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String header = null;
|
||||
|
||||
int counter = 0;
|
||||
for (Entry<String, List<String>> entry: headers.entrySet()) {
|
||||
if (counter == idx) {
|
||||
String key = entry.getKey();
|
||||
if (null == key) {
|
||||
header = listToString(entry.getValue(), ",") + "\n";
|
||||
} else {
|
||||
header = key + ":" + listToString(entry.getValue(), ",") + "\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
static String getResponseHeaderByKey(HttpURLConnection http, String key) {
|
||||
if (null == key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, List<String>> headers = http.getHeaderFields();
|
||||
if (null == headers) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String header = null;
|
||||
|
||||
for (Entry<String, List<String>> entry: headers.entrySet()) {
|
||||
if (key.equalsIgnoreCase(entry.getKey())) {
|
||||
if ("set-cookie".equalsIgnoreCase(key)) {
|
||||
header = combinCookies(entry.getValue(), http.getURL().getHost());
|
||||
} else {
|
||||
header = listToString(entry.getValue(), ",");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
static int getResponseHeaderByKeyInt(HttpURLConnection http, String key) {
|
||||
String value = http.getHeaderField(key);
|
||||
|
||||
if (null == value) {
|
||||
return 0;
|
||||
} else {
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] getResponseContent(HttpURLConnection http) {
|
||||
InputStream in;
|
||||
try {
|
||||
in = http.getInputStream();
|
||||
String contentEncoding = http.getContentEncoding();
|
||||
if (contentEncoding != null) {
|
||||
if(contentEncoding.equalsIgnoreCase("gzip")){
|
||||
in = new GZIPInputStream(http.getInputStream()); //reads 2 bytes to determine GZIP stream!
|
||||
}
|
||||
else if(contentEncoding.equalsIgnoreCase("deflate")){
|
||||
in = new InflaterInputStream(http.getInputStream());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
in = http.getErrorStream();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "1 getResponseContent: " + e.toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] buffer = new byte[1024];
|
||||
int size = 0;
|
||||
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
|
||||
while((size = in.read(buffer, 0 , 1024)) != -1)
|
||||
{
|
||||
bytestream.write(buffer, 0, size);
|
||||
}
|
||||
byte retbuffer[] = bytestream.toByteArray();
|
||||
bytestream.close();
|
||||
return retbuffer;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "2 getResponseContent:" + e.toString());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static int getResponseCode(HttpURLConnection http) {
|
||||
int code = 0;
|
||||
try {
|
||||
code = http.getResponseCode();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "getResponseCode:" + e.toString());
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static String getResponseMessage(HttpURLConnection http) {
|
||||
String msg;
|
||||
try {
|
||||
msg = http.getResponseMessage();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
msg = e.toString();
|
||||
Log.e(TAG, "getResponseMessage: " + msg);
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
public static String listToString(List<String> list, String strInterVal) {
|
||||
if (list == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
boolean flag = false;
|
||||
for (String str : list) {
|
||||
if (flag) {
|
||||
result.append(strInterVal);
|
||||
}
|
||||
if (null == str) {
|
||||
str = "";
|
||||
}
|
||||
result.append(str);
|
||||
flag = true;
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String combinCookies(List<String> list, String hostDomain) {
|
||||
StringBuilder sbCookies = new StringBuilder();
|
||||
String domain = hostDomain;
|
||||
String tailmatch = "FALSE";
|
||||
String path = "/";
|
||||
String secure = "FALSE";
|
||||
String key = null;
|
||||
String value = null;
|
||||
String expires = null;
|
||||
for (String str : list) {
|
||||
String[] parts = str.split(";");
|
||||
for (String part : parts) {
|
||||
int firstIndex = part.indexOf("=");
|
||||
if (-1 == firstIndex)
|
||||
continue;
|
||||
|
||||
String[] item = {part.substring(0, firstIndex), part.substring(firstIndex + 1)};
|
||||
if ("expires".equalsIgnoreCase(item[0].trim())) {
|
||||
expires = str2Seconds(item[1].trim());
|
||||
} else if("path".equalsIgnoreCase(item[0].trim())) {
|
||||
path = item[1];
|
||||
} else if("secure".equalsIgnoreCase(item[0].trim())) {
|
||||
secure = item[1];
|
||||
} else if("domain".equalsIgnoreCase(item[0].trim())) {
|
||||
domain = item[1];
|
||||
} else if("version".equalsIgnoreCase(item[0].trim()) || "max-age".equalsIgnoreCase(item[0].trim())) {
|
||||
//do nothing
|
||||
} else {
|
||||
key = item[0];
|
||||
value = item[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (null == domain) {
|
||||
domain = "none";
|
||||
}
|
||||
|
||||
sbCookies.append(domain);
|
||||
sbCookies.append('\t');
|
||||
sbCookies.append(tailmatch); //access
|
||||
sbCookies.append('\t');
|
||||
sbCookies.append(path); //path
|
||||
sbCookies.append('\t');
|
||||
sbCookies.append(secure); //secure
|
||||
sbCookies.append('\t');
|
||||
sbCookies.append(expires); //expires
|
||||
sbCookies.append("\t");
|
||||
sbCookies.append(key); //key
|
||||
sbCookies.append("\t");
|
||||
sbCookies.append(value); //value
|
||||
sbCookies.append('\n');
|
||||
}
|
||||
|
||||
return sbCookies.toString();
|
||||
}
|
||||
|
||||
private static String str2Seconds(String strTime) {
|
||||
Calendar c = Calendar.getInstance();
|
||||
long milliseconds = 0;
|
||||
|
||||
try {
|
||||
c.setTime(new SimpleDateFormat("EEE, dd-MMM-yy hh:mm:ss zzz", Locale.US).parse(strTime));
|
||||
milliseconds = c.getTimeInMillis() / 1000;
|
||||
} catch (ParseException e) {
|
||||
Log.e(TAG, "str2Seconds: " + e.toString());
|
||||
}
|
||||
|
||||
return Long.toString(milliseconds);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
* Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
public class Cocos2dxJavascriptJavaBridge {
|
||||
public static native int evalString(String value);
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
|
||||
public class Cocos2dxLocalStorage {
|
||||
|
||||
private static final String TAG = "Cocos2dxLocalStorage";
|
||||
|
||||
private static String DATABASE_NAME = "jsb.sqlite";
|
||||
private static String TABLE_NAME = "data";
|
||||
private static final int DATABASE_VERSION = 1;
|
||||
|
||||
private static DBOpenHelper mDatabaseOpenHelper = null;
|
||||
private static SQLiteDatabase mDatabase = null;
|
||||
/**
|
||||
* Constructor
|
||||
* @param context The Context within which to work, used to create the DB
|
||||
* @return
|
||||
*/
|
||||
public static boolean init(String dbName, String tableName) {
|
||||
if (Cocos2dxActivity.getContext() != null) {
|
||||
DATABASE_NAME = dbName;
|
||||
TABLE_NAME = tableName;
|
||||
mDatabaseOpenHelper = new DBOpenHelper(Cocos2dxActivity.getContext());
|
||||
mDatabase = mDatabaseOpenHelper.getWritableDatabase();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void destroy() {
|
||||
if (mDatabase != null) {
|
||||
mDatabase.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setItem(String key, String value) {
|
||||
try {
|
||||
String sql = "replace into "+TABLE_NAME+"(key,value)values(?,?)";
|
||||
mDatabase.execSQL(sql, new Object[] { key, value });
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getItem(String key) {
|
||||
String ret = null;
|
||||
try {
|
||||
String sql = "select value from "+TABLE_NAME+" where key=?";
|
||||
Cursor c = mDatabase.rawQuery(sql, new String[]{key});
|
||||
while (c.moveToNext()) {
|
||||
// only return the first value
|
||||
if (ret != null)
|
||||
{
|
||||
Log.e(TAG, "The key contains more than one value.");
|
||||
break;
|
||||
}
|
||||
ret = c.getString(c.getColumnIndex("value"));
|
||||
}
|
||||
c.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void removeItem(String key) {
|
||||
try {
|
||||
String sql = "delete from "+TABLE_NAME+" where key=?";
|
||||
mDatabase.execSQL(sql, new Object[] {key});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
try {
|
||||
String sql = "delete from "+TABLE_NAME;
|
||||
mDatabase.execSQL(sql);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getKey(int nIndex) {
|
||||
String ret = null;
|
||||
try {
|
||||
int nCount = 0;
|
||||
String sql = "select key from "+TABLE_NAME + " order by rowid asc";
|
||||
Cursor c = mDatabase.rawQuery(sql, null);
|
||||
if(nIndex < 0 || nIndex >= c.getCount()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
while (c.moveToNext()) {
|
||||
if(nCount == nIndex) {
|
||||
ret = c.getString(c.getColumnIndex("key"));
|
||||
break;
|
||||
}
|
||||
nCount++;
|
||||
}
|
||||
c.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int getLength() {
|
||||
int res = 0;
|
||||
try {
|
||||
String sql = "select count(*) as nums from "+TABLE_NAME;
|
||||
Cursor c = mDatabase.rawQuery(sql, null);
|
||||
if (c.moveToNext()){
|
||||
res = c.getInt(c.getColumnIndex("nums"));
|
||||
}
|
||||
c.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates/opens the database.
|
||||
*/
|
||||
private static class DBOpenHelper extends SQLiteOpenHelper {
|
||||
|
||||
DBOpenHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE IF NOT EXISTS "+TABLE_NAME+"(key TEXT PRIMARY KEY,value TEXT);");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
|
||||
+ newVersion + ", which will destroy all old data");
|
||||
//db.execSQL("DROP TABLE IF EXISTS " + VIRTUAL_TABLE);
|
||||
//onCreate(db);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.OrientationEventListener;
|
||||
|
||||
public class Cocos2dxOrientationHelper extends OrientationEventListener {
|
||||
|
||||
private int currentOrientation;
|
||||
|
||||
public Cocos2dxOrientationHelper(Context context) {
|
||||
super(context);
|
||||
currentOrientation = Cocos2dxHelper.getDeviceRotation();
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
this.disable();
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
this.enable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOrientationChanged(int orientation) {
|
||||
int curOrientation = Cocos2dxHelper.getDeviceRotation();
|
||||
if (curOrientation != currentOrientation) {
|
||||
currentOrientation = Cocos2dxHelper.getDeviceRotation();
|
||||
nativeOnOrientationChanged(currentOrientation);
|
||||
}
|
||||
}
|
||||
|
||||
public static native void nativeOnOrientationChanged(int rotation);
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2016 cocos2d-x.org
|
||||
Copyright (c) 2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
public class Cocos2dxReflectionHelper {
|
||||
public static <T> T getConstantValue(final Class aClass, final String constantName) {
|
||||
try {
|
||||
return (T)aClass.getDeclaredField(constantName).get(null);
|
||||
} catch (NoSuchFieldException e) {
|
||||
Log.e("error", "can not find " + constantName + " in " + aClass.getName());
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
Log.e("error", constantName + " is not accessable");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
Log.e("error", "arguments error when get " + constantName);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Log.e("error", "can not get constant" + constantName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> T invokeInstanceMethod(final Object instance, final String methodName,
|
||||
final Class[] parameterTypes, final Object[] parameters) {
|
||||
|
||||
final Class aClass = instance.getClass();
|
||||
try {
|
||||
final Method method = aClass.getMethod(methodName, parameterTypes);
|
||||
return (T)method.invoke(instance, parameters);
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log.e("error", "can not find " + methodName + " in " + aClass.getName());
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
Log.e("error", methodName + " is not accessible");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
Log.e("error", "arguments are error when invoking " + methodName);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
Log.e("error", "an exception was thrown by the invoked method when invoking " + methodName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> T invokeInterfaceMethod(final Class clazz, final String methodName,
|
||||
final Class[] parameterTypes, final Object[] parameters) {
|
||||
|
||||
try {
|
||||
final Method method = clazz.getMethod(methodName, parameterTypes);
|
||||
return (T)method.invoke(null, parameters);
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log.e("error", "can not find " + methodName + " in " + clazz.getName());
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
Log.e("error", methodName + " is not accessible");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
Log.e("error", "arguments are error when invoking " + methodName);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
Log.e("error", "an exception was thrown by the invoked method when invoking " + methodName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object createInstanceInterface(final String className, final String interfaceName) {
|
||||
try {
|
||||
final Class clazz = Class.forName(className + "$" + interfaceName);
|
||||
return Proxy.newProxyInstance(clazz.getClassLoader(),
|
||||
new Class<?>[]{clazz}, new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (ClassNotFoundException ex) {
|
||||
Log.e("error", "can not find " + className + "." + interfaceName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Class getClassByName(final String className) {
|
||||
try {
|
||||
return Class.forName(className);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
Log.e("error", "can not find " + className);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Class getInterfaceByName(final String className, final String interfaceName) {
|
||||
try {
|
||||
return Class.forName(className + "$" + interfaceName);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
Log.e("error", "can not find " + className + "." + interfaceName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2011 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.opengl.GLSurfaceView;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
public class Cocos2dxRenderer implements GLSurfaceView.Renderer {
|
||||
// ===========================================================
|
||||
// Constants
|
||||
// ===========================================================
|
||||
private final static String TAG = "Cocos2dxRenderer";
|
||||
|
||||
private final static long NANOSECONDSPERSECOND = 1000000000L;
|
||||
private final static long NANOSECONDSPERMICROSECOND = 1000000;
|
||||
|
||||
private static final long INTERVAL_60_FPS = (long) (1.0 / 60 * Cocos2dxRenderer.NANOSECONDSPERSECOND);
|
||||
private static long sAnimationInterval = INTERVAL_60_FPS;
|
||||
private static WeakReference<Cocos2dxRenderer> sRenderer;
|
||||
|
||||
// ===========================================================
|
||||
// Fields
|
||||
// ===========================================================
|
||||
|
||||
private long mLastTickInNanoSeconds;
|
||||
private int mScreenWidth;
|
||||
private int mScreenHeight;
|
||||
private boolean mNativeInitCompleted = false;
|
||||
private boolean mNeedShowFPS = false;
|
||||
private String mDefaultResourcePath = "";
|
||||
private long mOldNanoTime = 0;
|
||||
private long mFrameCount = 0;
|
||||
private boolean mNeedToPause = false;
|
||||
|
||||
// ===========================================================
|
||||
// Constructors
|
||||
// ===========================================================
|
||||
|
||||
// ===========================================================
|
||||
// Getter & Setter
|
||||
// ===========================================================
|
||||
|
||||
public static void setPreferredFramesPerSecond(int fps) {
|
||||
Cocos2dxRenderer.sAnimationInterval = (long) (1.0 / fps * Cocos2dxRenderer.NANOSECONDSPERSECOND);
|
||||
}
|
||||
|
||||
public void setScreenWidthAndHeight(final int surfaceWidth, final int surfaceHeight) {
|
||||
this.mScreenWidth = surfaceWidth;
|
||||
this.mScreenHeight = surfaceHeight;
|
||||
}
|
||||
|
||||
public void setDefaultResourcePath(String path) {
|
||||
if (path == null)
|
||||
return;
|
||||
mDefaultResourcePath = path;
|
||||
}
|
||||
|
||||
public void showFPS() {
|
||||
mNeedShowFPS = true;
|
||||
}
|
||||
|
||||
public interface OnGameEngineInitializedListener {
|
||||
void onGameEngineInitialized();
|
||||
}
|
||||
|
||||
private OnGameEngineInitializedListener mGameEngineInitializedListener;
|
||||
|
||||
public void setOnGameEngineInitializedListener(OnGameEngineInitializedListener listener) {
|
||||
mGameEngineInitializedListener = listener;
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Methods for/from SuperClass/Interfaces
|
||||
// ===========================================================
|
||||
|
||||
@Override
|
||||
public void onSurfaceCreated(final GL10 GL10, final EGLConfig EGLConfig) {
|
||||
mNativeInitCompleted = false;
|
||||
Cocos2dxRenderer.nativeInit(this.mScreenWidth, this.mScreenHeight, mDefaultResourcePath);
|
||||
mOldNanoTime = System.nanoTime();
|
||||
this.mLastTickInNanoSeconds = System.nanoTime();
|
||||
mNativeInitCompleted = true;
|
||||
if (mGameEngineInitializedListener != null) {
|
||||
Cocos2dxHelper.getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mGameEngineInitializedListener.onGameEngineInitialized();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceChanged(final GL10 GL10, final int width, final int height) {
|
||||
Cocos2dxRenderer.nativeOnSurfaceChanged(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawFrame(final GL10 gl) {
|
||||
if (mNeedToPause)
|
||||
return;
|
||||
|
||||
if (mNeedShowFPS) {
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//IDEA: show FPS in Android Text control rather than outputing log.
|
||||
++mFrameCount;
|
||||
long nowFpsTime = System.nanoTime();
|
||||
long fpsTimeInterval = nowFpsTime - mOldNanoTime;
|
||||
if (fpsTimeInterval > 1000000000L) {
|
||||
double frameRate = 1000000000.0 * mFrameCount / fpsTimeInterval;
|
||||
Cocos2dxHelper.OnGameInfoUpdatedListener listener = Cocos2dxHelper.getOnGameInfoUpdatedListener();
|
||||
if (listener != null) {
|
||||
listener.onFPSUpdated((float) frameRate);
|
||||
}
|
||||
mFrameCount = 0;
|
||||
mOldNanoTime = System.nanoTime();
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
/*
|
||||
* No need to use algorithm in default(60 FPS) situation,
|
||||
* since onDrawFrame() was called by system 60 times per second by default.
|
||||
*/
|
||||
if (sAnimationInterval <= INTERVAL_60_FPS) {
|
||||
Cocos2dxRenderer.nativeRender();
|
||||
} else {
|
||||
final long now = System.nanoTime();
|
||||
final long interval = now - this.mLastTickInNanoSeconds;
|
||||
|
||||
if (interval < Cocos2dxRenderer.sAnimationInterval) {
|
||||
try {
|
||||
Thread.sleep((Cocos2dxRenderer.sAnimationInterval - interval) / Cocos2dxRenderer.NANOSECONDSPERMICROSECOND);
|
||||
} catch (final Exception e) {
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Render time MUST be counted in, or the FPS will slower than appointed.
|
||||
*/
|
||||
this.mLastTickInNanoSeconds = System.nanoTime();
|
||||
Cocos2dxRenderer.nativeRender();
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Methods
|
||||
// ===========================================================
|
||||
|
||||
private static native void nativeTouchesBegin(final int id, final float x, final float y);
|
||||
private static native void nativeTouchesEnd(final int id, final float x, final float y);
|
||||
private static native void nativeTouchesMove(final int[] ids, final float[] xs, final float[] ys);
|
||||
private static native void nativeTouchesCancel(final int[] ids, final float[] xs, final float[] ys);
|
||||
private static native boolean nativeKeyEvent(final int keyCode,boolean isPressed);
|
||||
private static native void nativeRender();
|
||||
private static native void nativeInit(final int width, final int height, final String resourcePath);
|
||||
private static native void nativeOnSurfaceChanged(final int width, final int height);
|
||||
private static native void nativeOnPause();
|
||||
private static native void nativeOnResume();
|
||||
|
||||
// This function will be invoked in main thread.
|
||||
public void setPauseInMainThread(boolean value) {
|
||||
mNeedToPause = value;
|
||||
}
|
||||
|
||||
public void handleActionDown(final int id, final float x, final float y) {
|
||||
if (! mNativeInitCompleted)
|
||||
return;
|
||||
|
||||
Cocos2dxRenderer.nativeTouchesBegin(id, x, y);
|
||||
}
|
||||
|
||||
public void handleActionUp(final int id, final float x, final float y) {
|
||||
if (! mNativeInitCompleted)
|
||||
return;
|
||||
|
||||
Cocos2dxRenderer.nativeTouchesEnd(id, x, y);
|
||||
}
|
||||
|
||||
public void handleActionCancel(final int[] ids, final float[] xs, final float[] ys) {
|
||||
if (! mNativeInitCompleted)
|
||||
return;
|
||||
|
||||
Cocos2dxRenderer.nativeTouchesCancel(ids, xs, ys);
|
||||
}
|
||||
|
||||
public void handleActionMove(final int[] ids, final float[] xs, final float[] ys) {
|
||||
if (! mNativeInitCompleted)
|
||||
return;
|
||||
|
||||
Cocos2dxRenderer.nativeTouchesMove(ids, xs, ys);
|
||||
}
|
||||
|
||||
public void handleKeyDown(final int keyCode) {
|
||||
if (! mNativeInitCompleted)
|
||||
return;
|
||||
|
||||
Cocos2dxRenderer.nativeKeyEvent(keyCode, true);
|
||||
}
|
||||
|
||||
public void handleKeyUp(final int keyCode) {
|
||||
if (! mNativeInitCompleted)
|
||||
return;
|
||||
|
||||
Cocos2dxRenderer.nativeKeyEvent(keyCode, false);
|
||||
}
|
||||
|
||||
public void handleOnPause() {
|
||||
/**
|
||||
* onPause may be invoked before onSurfaceCreated,
|
||||
* and engine will be initialized correctly after
|
||||
* onSurfaceCreated is invoked. Can not invoke any
|
||||
* native method before onSurfaceCreated is invoked
|
||||
*/
|
||||
if (! mNativeInitCompleted)
|
||||
return;
|
||||
|
||||
Cocos2dxHelper.onEnterBackground();
|
||||
Cocos2dxRenderer.nativeOnPause();
|
||||
}
|
||||
|
||||
public void handleOnResume() {
|
||||
Cocos2dxHelper.onEnterForeground();
|
||||
Cocos2dxRenderer.nativeOnResume();
|
||||
}
|
||||
|
||||
private static native void nativeInsertText(final String text);
|
||||
private static native void nativeDeleteBackward();
|
||||
private static native String nativeGetContentText();
|
||||
|
||||
public void handleInsertText(final String text) {
|
||||
Cocos2dxRenderer.nativeInsertText(text);
|
||||
}
|
||||
|
||||
public void handleDeleteBackward() {
|
||||
Cocos2dxRenderer.nativeDeleteBackward();
|
||||
}
|
||||
|
||||
public String getContentText() {
|
||||
return Cocos2dxRenderer.nativeGetContentText();
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Inner and Anonymous Classes
|
||||
// ===========================================================
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Cocos2dxTypefaces {
|
||||
// ===========================================================
|
||||
// Constants
|
||||
// ===========================================================
|
||||
|
||||
// ===========================================================
|
||||
// Fields
|
||||
// ===========================================================
|
||||
|
||||
private static final HashMap<String, Typeface> sTypefaceCache = new HashMap<String, Typeface>();
|
||||
|
||||
// ===========================================================
|
||||
// Constructors
|
||||
// ===========================================================
|
||||
|
||||
// ===========================================================
|
||||
// Getter & Setter
|
||||
// ===========================================================
|
||||
|
||||
// ===========================================================
|
||||
// Methods for/from SuperClass/Interfaces
|
||||
// ===========================================================
|
||||
|
||||
// ===========================================================
|
||||
// Methods
|
||||
// ===========================================================
|
||||
|
||||
public static synchronized Typeface get(final Context context, final String assetName) {
|
||||
if (!Cocos2dxTypefaces.sTypefaceCache.containsKey(assetName)) {
|
||||
Typeface typeface = null;
|
||||
if (assetName.startsWith("/"))
|
||||
{
|
||||
typeface = Typeface.createFromFile(assetName);
|
||||
}
|
||||
else
|
||||
{
|
||||
typeface = Typeface.createFromAsset(context.getAssets(), assetName);
|
||||
}
|
||||
Cocos2dxTypefaces.sTypefaceCache.put(assetName, typeface);
|
||||
}
|
||||
|
||||
return Cocos2dxTypefaces.sTypefaceCache.get(assetName);
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Inner and Anonymous Classes
|
||||
// ===========================================================
|
||||
|
||||
}
|
||||
@@ -0,0 +1,575 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2014-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import org.cocos2dx.lib.Cocos2dxVideoView.OnVideoEventListener;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
public class Cocos2dxVideoHelper {
|
||||
|
||||
private FrameLayout mLayout = null;
|
||||
private Cocos2dxActivity mActivity = null;
|
||||
private static SparseArray<Cocos2dxVideoView> sVideoViews = null;
|
||||
static VideoHandler mVideoHandler = null;
|
||||
private static Handler sHandler = null;
|
||||
|
||||
Cocos2dxVideoHelper(Cocos2dxActivity activity, FrameLayout layout)
|
||||
{
|
||||
mActivity = activity;
|
||||
mLayout = layout;
|
||||
|
||||
mVideoHandler = new VideoHandler(this);
|
||||
sVideoViews = new SparseArray<Cocos2dxVideoView>();
|
||||
sHandler = new Handler(Looper.myLooper());
|
||||
}
|
||||
|
||||
private static int videoTag = 0;
|
||||
private final static int VideoTaskCreate = 0;
|
||||
private final static int VideoTaskRemove = 1;
|
||||
private final static int VideoTaskSetSource = 2;
|
||||
private final static int VideoTaskSetRect = 3;
|
||||
private final static int VideoTaskStart = 4;
|
||||
private final static int VideoTaskPause = 5;
|
||||
private final static int VideoTaskResume = 6;
|
||||
private final static int VideoTaskStop = 7;
|
||||
private final static int VideoTaskSeek = 8;
|
||||
private final static int VideoTaskSetVisible = 9;
|
||||
private final static int VideoTaskRestart = 10;
|
||||
private final static int VideoTaskKeepRatio = 11;
|
||||
private final static int VideoTaskFullScreen = 12;
|
||||
private final static int VideoTaskSetVolume = 13;
|
||||
|
||||
final static int KeyEventBack = 1000;
|
||||
|
||||
static class VideoHandler extends Handler{
|
||||
WeakReference<Cocos2dxVideoHelper> mReference;
|
||||
|
||||
VideoHandler(Cocos2dxVideoHelper helper){
|
||||
mReference = new WeakReference<Cocos2dxVideoHelper>(helper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
Cocos2dxVideoHelper helper = mReference.get();
|
||||
switch (msg.what) {
|
||||
case VideoTaskCreate: {
|
||||
helper._createVideoView(msg.arg1);
|
||||
break;
|
||||
}
|
||||
case VideoTaskRemove: {
|
||||
helper._removeVideoView(msg.arg1);
|
||||
break;
|
||||
}
|
||||
case VideoTaskSetSource: {
|
||||
helper._setVideoURL(msg.arg1, msg.arg2, (String)msg.obj);
|
||||
break;
|
||||
}
|
||||
case VideoTaskStart: {
|
||||
helper._startVideo(msg.arg1);
|
||||
break;
|
||||
}
|
||||
case VideoTaskSetRect: {
|
||||
Rect rect = (Rect)msg.obj;
|
||||
helper._setVideoRect(msg.arg1, rect.left, rect.top, rect.right, rect.bottom);
|
||||
break;
|
||||
}
|
||||
case VideoTaskFullScreen:{
|
||||
if (msg.arg2 == 1) {
|
||||
helper._setFullScreenEnabled(msg.arg1, true);
|
||||
} else {
|
||||
helper._setFullScreenEnabled(msg.arg1, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VideoTaskPause: {
|
||||
helper._pauseVideo(msg.arg1);
|
||||
break;
|
||||
}
|
||||
|
||||
case VideoTaskStop: {
|
||||
helper._stopVideo(msg.arg1);
|
||||
break;
|
||||
}
|
||||
case VideoTaskSeek: {
|
||||
helper._seekVideoTo(msg.arg1, msg.arg2);
|
||||
break;
|
||||
}
|
||||
case VideoTaskSetVisible: {
|
||||
if (msg.arg2 == 1) {
|
||||
helper._setVideoVisible(msg.arg1, true);
|
||||
} else {
|
||||
helper._setVideoVisible(msg.arg1, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VideoTaskKeepRatio: {
|
||||
if (msg.arg2 == 1) {
|
||||
helper._setVideoKeepRatio(msg.arg1, true);
|
||||
} else {
|
||||
helper._setVideoKeepRatio(msg.arg1, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KeyEventBack: {
|
||||
helper.onBackKeyEvent();
|
||||
break;
|
||||
}
|
||||
case VideoTaskSetVolume: {
|
||||
float volume = (float) msg.arg2 / 10;
|
||||
helper._setVolume(msg.arg1, volume);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
super.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private class VideoEventRunnable implements Runnable
|
||||
{
|
||||
private int mVideoTag;
|
||||
private int mVideoEvent;
|
||||
|
||||
public VideoEventRunnable(int tag,int event) {
|
||||
mVideoTag = tag;
|
||||
mVideoEvent = event;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
nativeExecuteVideoCallback(mVideoTag, mVideoEvent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static native void nativeExecuteVideoCallback(int index,int event);
|
||||
|
||||
OnVideoEventListener videoEventListener = new OnVideoEventListener() {
|
||||
|
||||
@Override
|
||||
public void onVideoEvent(int tag,int event) {
|
||||
mActivity.runOnGLThread(new VideoEventRunnable(tag, event));
|
||||
}
|
||||
};
|
||||
|
||||
public static int createVideoWidget() {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskCreate;
|
||||
msg.arg1 = videoTag;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
|
||||
return videoTag++;
|
||||
}
|
||||
|
||||
private void _createVideoView(int index) {
|
||||
Cocos2dxVideoView videoView = new Cocos2dxVideoView(mActivity,index);
|
||||
sVideoViews.put(index, videoView);
|
||||
FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT);
|
||||
mLayout.addView(videoView, lParams);
|
||||
videoView.setZOrderOnTop(true);
|
||||
videoView.setVideoViewEventListener(videoEventListener);
|
||||
}
|
||||
|
||||
public static void removeVideoWidget(int index){
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskRemove;
|
||||
msg.arg1 = index;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _removeVideoView(int index) {
|
||||
Cocos2dxVideoView view = sVideoViews.get(index);
|
||||
if (view != null) {
|
||||
view.stopPlayback();
|
||||
sVideoViews.remove(index);
|
||||
mLayout.removeView(view);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVideoUrl(int index, int videoSource, String videoUrl) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskSetSource;
|
||||
msg.arg1 = index;
|
||||
msg.arg2 = videoSource;
|
||||
msg.obj = videoUrl;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _setVideoURL(int index, int videoSource, String videoUrl) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
switch (videoSource) {
|
||||
case 0:
|
||||
videoView.setVideoFileName(videoUrl);
|
||||
break;
|
||||
case 1:
|
||||
videoView.setVideoURL(videoUrl);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVideoRect(int index, int left, int top, int maxWidth, int maxHeight) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskSetRect;
|
||||
msg.arg1 = index;
|
||||
msg.obj = new Rect(left, top, maxWidth, maxHeight);
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _setVideoRect(int index, int left, int top, int maxWidth, int maxHeight) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.setVideoRect(left,top,maxWidth,maxHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setFullScreenEnabled(int index, boolean enabled) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskFullScreen;
|
||||
msg.arg1 = index;
|
||||
if (enabled) {
|
||||
msg.arg2 = 1;
|
||||
} else {
|
||||
msg.arg2 = 0;
|
||||
}
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _setFullScreenEnabled(int index, boolean enabled) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.setFullScreenEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
private void onBackKeyEvent() {
|
||||
int viewCount = sVideoViews.size();
|
||||
for (int i = 0; i < viewCount; i++) {
|
||||
int key = sVideoViews.keyAt(i);
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(key);
|
||||
if (videoView != null) {
|
||||
videoView.setFullScreenEnabled(false);
|
||||
mActivity.runOnGLThread(new VideoEventRunnable(key, KeyEventBack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void startVideo(int index) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskStart;
|
||||
msg.arg1 = index;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _startVideo(int index) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.start();
|
||||
}
|
||||
}
|
||||
|
||||
public static void pauseVideo(int index) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskPause;
|
||||
msg.arg1 = index;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _pauseVideo(int index) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.pause();
|
||||
}
|
||||
}
|
||||
|
||||
public static void stopVideo(int index) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskStop;
|
||||
msg.arg1 = index;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _stopVideo(int index) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public static void seekVideoTo(int index,int msec) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskSeek;
|
||||
msg.arg1 = index;
|
||||
msg.arg2 = msec;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _seekVideoTo(int index,int msec) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.seekTo(msec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static <T> T callInMainThread(Callable<T> call) throws ExecutionException, InterruptedException {
|
||||
FutureTask<T> task = new FutureTask<T>(call);
|
||||
sHandler.post(task);
|
||||
return task.get();
|
||||
}
|
||||
|
||||
public static float getCurrentTime(final int index) {
|
||||
Callable<Float> callable = new Callable<Float>() {
|
||||
@Override
|
||||
public Float call() throws Exception {
|
||||
Cocos2dxVideoView video = sVideoViews.get(index);
|
||||
float currentPosition = -1;
|
||||
if (video != null) {
|
||||
currentPosition = video.getCurrentPosition() / 1000.0f;
|
||||
}
|
||||
return new Float(currentPosition);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
return callInMainThread(callable);
|
||||
} catch (ExecutionException e) {
|
||||
return -1;
|
||||
} catch (InterruptedException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static float getDuration(final int index) {
|
||||
Callable<Float> callable = new Callable<Float>() {
|
||||
@Override
|
||||
public Float call() throws Exception {
|
||||
Cocos2dxVideoView video = sVideoViews.get(index);
|
||||
float duration = -1;
|
||||
if (video != null) {
|
||||
duration = video.getDuration() / 1000.0f;
|
||||
}
|
||||
if (duration <= 0) {
|
||||
Log.w("Cocos2dxVideoHelper", "Video player's duration is not ready to get now!");
|
||||
}
|
||||
return new Float(duration);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
return callInMainThread(callable);
|
||||
} catch (ExecutionException e) {
|
||||
return -1;
|
||||
} catch (InterruptedException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVideoVisible(int index, boolean visible) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskSetVisible;
|
||||
msg.arg1 = index;
|
||||
if (visible) {
|
||||
msg.arg2 = 1;
|
||||
} else {
|
||||
msg.arg2 = 0;
|
||||
}
|
||||
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _setVideoVisible(int index, boolean visible) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
if (visible) {
|
||||
videoView.fixSize();
|
||||
videoView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
videoView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVideoKeepRatioEnabled(int index, boolean enable) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskKeepRatio;
|
||||
msg.arg1 = index;
|
||||
if (enable) {
|
||||
msg.arg2 = 1;
|
||||
} else {
|
||||
msg.arg2 = 0;
|
||||
}
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _setVideoKeepRatio(int index, boolean enable) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.setKeepRatio(enable);
|
||||
}
|
||||
}
|
||||
|
||||
private void _setVolume(final int index, final float volume) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.setVolume(volume);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVolume(final int index, final float volume) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskSetVolume;
|
||||
msg.arg1 = index;
|
||||
msg.arg2 = (int) (volume * 10);
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private byte[] getFrame(final int index) {
|
||||
Callable<byte[]> callable = new Callable<byte[]>() {
|
||||
@Override
|
||||
public byte[] call() throws Exception {
|
||||
Cocos2dxVideoView video = sVideoViews.get(index);
|
||||
byte datas[] = null;
|
||||
if (video != null) datas = video.getFrame();
|
||||
if (datas == null) {
|
||||
Log.w("Cocos2dxVideoHelper", "Video player's frame is not ready to get now!");
|
||||
}
|
||||
return datas;
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
return callInMainThread(callable);
|
||||
} catch (ExecutionException e) {
|
||||
Log.w("ExecutionException", e.getMessage());
|
||||
return null;
|
||||
} catch (InterruptedException e) {
|
||||
Log.w("InterruptedException", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private float getFrameChannel(final int index) {
|
||||
Callable<Float> callable = new Callable<Float>() {
|
||||
@Override
|
||||
public Float call() throws Exception {
|
||||
Cocos2dxVideoView video = sVideoViews.get(index);
|
||||
int channel = 0;
|
||||
if (video != null) {
|
||||
channel = video.getFrameChannel();
|
||||
}
|
||||
if (channel == 0) {
|
||||
Log.w("Cocos2dxVideoHelper", "Video player's frame channel is unknown!");
|
||||
}
|
||||
return new Float((float)channel);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
return callInMainThread(callable);
|
||||
} catch (ExecutionException e) {
|
||||
return -1.0f;
|
||||
} catch (InterruptedException e) {
|
||||
return -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
private float getFrameWidth(final int index) {
|
||||
Callable<Float> callable = new Callable<Float>() {
|
||||
@Override
|
||||
public Float call() {
|
||||
Cocos2dxVideoView video = sVideoViews.get(index);
|
||||
int width = 0;
|
||||
if (video != null) {
|
||||
width = video.getFrameWidth();
|
||||
}
|
||||
if (width == 0) {
|
||||
Log.w("Cocos2dxVideoHelper", "Video player's frame width is not ready to get now!");
|
||||
}
|
||||
return new Float((float)width);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
return callInMainThread(callable);
|
||||
} catch (ExecutionException e) {
|
||||
return -1.0f;
|
||||
} catch (InterruptedException e) {
|
||||
return -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
private float getFrameHeight(final int index) {
|
||||
Callable<Float> callable = new Callable<Float>() {
|
||||
@Override
|
||||
public Float call() {
|
||||
Cocos2dxVideoView video = sVideoViews.get(index);
|
||||
int height = 0;
|
||||
if (video != null) {
|
||||
height = video.getFrameHeight();
|
||||
}
|
||||
if (height == 0) {
|
||||
Log.w("Cocos2dxVideoHelper", "Video player's frame height is not ready to get now!");
|
||||
}
|
||||
return new Float((float)height);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
return callInMainThread(callable);
|
||||
} catch (ExecutionException e) {
|
||||
return -1.0f;
|
||||
} catch (InterruptedException e) {
|
||||
return -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
private void setShowRawFrame(final int index, final boolean show) {
|
||||
Cocos2dxVideoView video = sVideoViews.get(index);
|
||||
if (video != null) {
|
||||
video.setShowRawFrame(show);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,717 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
* Copyright (c) 2014-2016 Chukong Technologies Inc.
|
||||
* Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.content.res.Resources;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.MediaMetadataRetriever;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.widget.FrameLayout;
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class Cocos2dxVideoView extends SurfaceView {
|
||||
|
||||
// ===========================================================
|
||||
// Internal classes and interfaces.
|
||||
// ===========================================================
|
||||
|
||||
public interface OnVideoEventListener
|
||||
{
|
||||
void onVideoEvent(int tag,int event);
|
||||
}
|
||||
|
||||
private enum State{
|
||||
IDLE,
|
||||
ERROR,
|
||||
INITIALIZED,
|
||||
PREPARING,
|
||||
PREPARED,
|
||||
STARTED,
|
||||
PAUSED,
|
||||
STOPPED,
|
||||
PLAYBACK_COMPLETED,
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Constants
|
||||
// ===========================================================
|
||||
private static final String AssetResourceRoot = "@assets/";
|
||||
|
||||
// ===========================================================
|
||||
// Fields
|
||||
// ===========================================================
|
||||
|
||||
private String TAG = "Cocos2dxVideoView";
|
||||
|
||||
private Uri mVideoUri;
|
||||
private int mDuration;
|
||||
|
||||
private State mCurrentState = State.IDLE;
|
||||
|
||||
// All the stuff we need for playing and showing a video
|
||||
private SurfaceHolder mSurfaceHolder = null;
|
||||
private MediaPlayer mMediaPlayer = null;
|
||||
private int mVideoWidth = 0;
|
||||
private int mVideoHeight = 0;
|
||||
|
||||
private OnVideoEventListener mOnVideoEventListener;
|
||||
|
||||
// recording the seek position while preparing
|
||||
private int mSeekWhenPrepared = 0;
|
||||
|
||||
protected Cocos2dxActivity mCocos2dxActivity = null;
|
||||
|
||||
protected int mViewLeft = 0;
|
||||
protected int mViewTop = 0;
|
||||
protected int mViewWidth = 0;
|
||||
protected int mViewHeight = 0;
|
||||
|
||||
protected int mVisibleLeft = 0;
|
||||
protected int mVisibleTop = 0;
|
||||
protected int mVisibleWidth = 0;
|
||||
protected int mVisibleHeight = 0;
|
||||
|
||||
protected boolean mFullScreenEnabled = false;
|
||||
protected int mFullScreenWidth = 0;
|
||||
protected int mFullScreenHeight = 0;
|
||||
|
||||
private boolean mIsAssetRouse = false;
|
||||
private String mVideoFilePath = null;
|
||||
|
||||
private int mViewTag = 0;
|
||||
private boolean mKeepRatio = false;
|
||||
private boolean mMetaUpdated = false;
|
||||
|
||||
private MediaMetadataRetriever mRetriever = null;
|
||||
private ByteBuffer mFrameBuf = null;
|
||||
private byte mPixels[] = null;
|
||||
private Bitmap mFrame = null;
|
||||
private Bitmap mCurFrame = null;
|
||||
private boolean mShowRaw = true;
|
||||
private Object mCopyListener = null;
|
||||
|
||||
private Surface mSurface = null;
|
||||
|
||||
private static final int PX_INVALID = 0;
|
||||
private static final int PX_ALPHA = 1;
|
||||
private static final int PX_ARGB_4444 = 2;
|
||||
private static final int PX_ARGB_8888 = 3;
|
||||
private static final int PX_HARDWARE = 4;
|
||||
private static final int PX_RGBA_F16 = 5;
|
||||
private static final int PX_RGB_565 = 6;
|
||||
|
||||
// MediaPlayer will be released when surface view is destroyed, so should record the position,
|
||||
// and use it to play after MedialPlayer is created again.
|
||||
private int mPositionBeforeRelease = 0;
|
||||
|
||||
// ===========================================================
|
||||
// Constructors
|
||||
// ===========================================================
|
||||
|
||||
public Cocos2dxVideoView(Cocos2dxActivity activity,int tag) {
|
||||
super(activity);
|
||||
|
||||
mViewTag = tag;
|
||||
mCocos2dxActivity = activity;
|
||||
initVideoView();
|
||||
setShowRawFrame(true); // Show mediaplayer window.
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Getter & Setter
|
||||
// ===========================================================
|
||||
|
||||
public void setVideoRect(int left, int top, int maxWidth, int maxHeight) {
|
||||
if (mViewLeft == left && mViewTop == top && mViewWidth == maxWidth && mViewHeight == maxHeight)
|
||||
return;
|
||||
|
||||
mViewLeft = left;
|
||||
mViewTop = top;
|
||||
mViewWidth = maxWidth;
|
||||
mViewHeight = maxHeight;
|
||||
|
||||
fixSize(mViewLeft, mViewTop, mViewWidth, mViewHeight);
|
||||
}
|
||||
|
||||
public void setFullScreenEnabled(boolean enabled) {
|
||||
if (mFullScreenEnabled != enabled) {
|
||||
mFullScreenEnabled = enabled;
|
||||
fixSize();
|
||||
}
|
||||
}
|
||||
|
||||
public void setVolume (float volume) {
|
||||
if (mMediaPlayer != null) {
|
||||
mMediaPlayer.setVolume(volume, volume);
|
||||
}
|
||||
}
|
||||
|
||||
public void setKeepRatio(boolean enabled) {
|
||||
mKeepRatio = enabled;
|
||||
fixSize();
|
||||
}
|
||||
|
||||
public void setVideoURL(String url) {
|
||||
mIsAssetRouse = false;
|
||||
setVideoURI(Uri.parse(url), null);
|
||||
}
|
||||
|
||||
public void setVideoFileName(String path) {
|
||||
if (path.startsWith(AssetResourceRoot)) {
|
||||
path = path.substring(AssetResourceRoot.length());
|
||||
}
|
||||
|
||||
if (path.startsWith("/")) {
|
||||
mIsAssetRouse = false;
|
||||
setVideoURI(Uri.parse(path),null);
|
||||
}
|
||||
else {
|
||||
|
||||
mVideoFilePath = path;
|
||||
mIsAssetRouse = true;
|
||||
setVideoURI(Uri.parse(path), null);
|
||||
}
|
||||
}
|
||||
|
||||
public int getCurrentPosition() {
|
||||
if (! (mCurrentState == State.ERROR |
|
||||
mMediaPlayer == null) ) {
|
||||
return mMediaPlayer.getCurrentPosition();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
if (! (mCurrentState == State.IDLE ||
|
||||
mCurrentState == State.ERROR ||
|
||||
mCurrentState == State.INITIALIZED ||
|
||||
mMediaPlayer == null) ) {
|
||||
mDuration = mMediaPlayer.getDuration();
|
||||
}
|
||||
|
||||
return mDuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be invoked when some video event triggered.
|
||||
*
|
||||
* @param l The callback that will be run
|
||||
*/
|
||||
public void setVideoViewEventListener(OnVideoEventListener l)
|
||||
{
|
||||
mOnVideoEventListener = l;
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Overrides
|
||||
// ===========================================================
|
||||
|
||||
@Override
|
||||
public void setVisibility(int visibility) {
|
||||
super.setVisibility(visibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
setMeasuredDimension(mVisibleWidth, mVisibleHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
|
||||
this.sendEvent(EVENT_CLICKED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Public functions
|
||||
// ===========================================================
|
||||
|
||||
public void stop() {
|
||||
if (!(mCurrentState == State.IDLE || mCurrentState == State.INITIALIZED || mCurrentState == State.ERROR || mCurrentState == State.STOPPED)
|
||||
&& mMediaPlayer != null) {
|
||||
mCurrentState = State.STOPPED;
|
||||
mMediaPlayer.stop();
|
||||
this.sendEvent(EVENT_STOPPED);
|
||||
|
||||
// after the video is stop, it shall prepare to be playable again
|
||||
try {
|
||||
mMediaPlayer.prepare();
|
||||
this.showFirstFrame();
|
||||
} catch (Exception ex) {}
|
||||
}
|
||||
}
|
||||
|
||||
public void stopPlayback() {
|
||||
this.release();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if ((mCurrentState == State.PREPARED ||
|
||||
mCurrentState == State.PAUSED ||
|
||||
mCurrentState == State.PLAYBACK_COMPLETED) &&
|
||||
mMediaPlayer != null) {
|
||||
|
||||
mCurrentState = State.STARTED;
|
||||
mMediaPlayer.start();
|
||||
this.sendEvent(EVENT_PLAYING);
|
||||
}
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
if ((mCurrentState == State.STARTED || mCurrentState == State.PLAYBACK_COMPLETED) &&
|
||||
mMediaPlayer != null) {
|
||||
mCurrentState = State.PAUSED;
|
||||
mMediaPlayer.pause();
|
||||
this.sendEvent(EVENT_PAUSED);
|
||||
}
|
||||
}
|
||||
|
||||
public void seekTo(int ms) {
|
||||
if (mCurrentState == State.IDLE || mCurrentState == State.INITIALIZED ||
|
||||
mCurrentState == State.STOPPED || mCurrentState == State.ERROR ||
|
||||
mMediaPlayer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mMediaPlayer.seekTo(ms);
|
||||
}
|
||||
|
||||
public void fixSize() {
|
||||
if (mFullScreenEnabled) {
|
||||
mFullScreenWidth = mCocos2dxActivity.getGLSurfaceView().getWidth();
|
||||
mFullScreenHeight = mCocos2dxActivity.getGLSurfaceView().getHeight();
|
||||
|
||||
fixSize(0, 0, mFullScreenWidth, mFullScreenHeight);
|
||||
} else {
|
||||
fixSize(mViewLeft, mViewTop, mViewWidth, mViewHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public void fixSize(int left, int top, int width, int height) {
|
||||
if (mVideoWidth == 0 || mVideoHeight == 0) {
|
||||
mVisibleLeft = left;
|
||||
mVisibleTop = top;
|
||||
mVisibleWidth = width;
|
||||
mVisibleHeight = height;
|
||||
}
|
||||
else if (width != 0 && height != 0) {
|
||||
if (mKeepRatio && !mFullScreenEnabled) {
|
||||
if ( mVideoWidth * height > width * mVideoHeight ) {
|
||||
mVisibleWidth = width;
|
||||
mVisibleHeight = width * mVideoHeight / mVideoWidth;
|
||||
} else if ( mVideoWidth * height < width * mVideoHeight ) {
|
||||
mVisibleWidth = height * mVideoWidth / mVideoHeight;
|
||||
mVisibleHeight = height;
|
||||
}
|
||||
mVisibleLeft = left + (width - mVisibleWidth) / 2;
|
||||
mVisibleTop = top + (height - mVisibleHeight) / 2;
|
||||
} else {
|
||||
mVisibleLeft = left;
|
||||
mVisibleTop = top;
|
||||
mVisibleWidth = width;
|
||||
mVisibleHeight = height;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mVisibleLeft = left;
|
||||
mVisibleTop = top;
|
||||
mVisibleWidth = mVideoWidth;
|
||||
mVisibleHeight = mVideoHeight;
|
||||
}
|
||||
|
||||
getHolder().setFixedSize(mVisibleWidth, mVisibleHeight);
|
||||
|
||||
FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
|
||||
FrameLayout.LayoutParams.MATCH_PARENT);
|
||||
lParams.leftMargin = mVisibleLeft;
|
||||
lParams.topMargin = mVisibleTop;
|
||||
setLayoutParams(lParams);
|
||||
}
|
||||
|
||||
public int resolveAdjustedSize(int desiredSize, int measureSpec) {
|
||||
int result = desiredSize;
|
||||
int specMode = MeasureSpec.getMode(measureSpec);
|
||||
int specSize = MeasureSpec.getSize(measureSpec);
|
||||
|
||||
switch (specMode) {
|
||||
case MeasureSpec.UNSPECIFIED:
|
||||
/* Parent says we can be as big as we want. Just don't be larger
|
||||
* than max size imposed on ourselves.
|
||||
*/
|
||||
result = desiredSize;
|
||||
break;
|
||||
|
||||
case MeasureSpec.AT_MOST:
|
||||
/* Parent says we can be as big as we want, up to specSize.
|
||||
* Don't be larger than specSize, and don't be larger than
|
||||
* the max size imposed on ourselves.
|
||||
*/
|
||||
result = Math.min(desiredSize, specSize);
|
||||
break;
|
||||
|
||||
case MeasureSpec.EXACTLY:
|
||||
// No choice. Do what we are told.
|
||||
result = specSize;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] getFrame() {
|
||||
if(mRetriever == null) {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT < 24) {
|
||||
mFrame = mRetriever.getFrameAtTime(mMediaPlayer.getCurrentPosition() * 1000, MediaMetadataRetriever.OPTION_CLOSEST);
|
||||
} else {
|
||||
if(mFrame == null) {
|
||||
Bitmap firstFrame = mRetriever.getFrameAtTime(0, MediaMetadataRetriever.OPTION_CLOSEST);
|
||||
mFrame = Bitmap.createBitmap(getWidth(), getHeight(), firstFrame.getConfig());
|
||||
}
|
||||
|
||||
if (mCopyListener == null) {
|
||||
mCopyListener = Cocos2dxReflectionHelper.createInstanceInterface("android.view.PixelCopy", "OnPixelCopyFinishedListener");
|
||||
}
|
||||
|
||||
final Class clazz = Cocos2dxReflectionHelper.getClassByName("android.view.PixelCopy");
|
||||
final Class intef = Cocos2dxReflectionHelper.getInterfaceByName("android.view.PixelCopy", "OnPixelCopyFinishedListener");
|
||||
final Class types[] = {SurfaceView.class, Bitmap.class, intef, Handler.class};
|
||||
final Object params[] = {this, mFrame, mCopyListener, this.getHandler()};
|
||||
|
||||
Cocos2dxReflectionHelper.invokeInterfaceMethod(clazz, "request", types, params);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("Grab error", e.getStackTrace().toString());
|
||||
return mPixels;
|
||||
}
|
||||
|
||||
if(mFrame == null) {
|
||||
return mPixels;
|
||||
}
|
||||
|
||||
mCurFrame = mFrame;
|
||||
|
||||
if(mFrameBuf == null) {
|
||||
mFrameBuf = ByteBuffer.allocate(mCurFrame.getByteCount());
|
||||
}
|
||||
mFrameBuf.position(0);
|
||||
mCurFrame.copyPixelsToBuffer(mFrameBuf);
|
||||
mPixels = mFrameBuf.array();
|
||||
|
||||
return mPixels;
|
||||
}
|
||||
}
|
||||
|
||||
public int getFrameChannel() throws NoSuchFieldException, IllegalAccessException {
|
||||
if (mCurFrame == null) {
|
||||
return 0;
|
||||
} else {
|
||||
Bitmap.Config cfg = mCurFrame.getConfig();
|
||||
if(Build.VERSION.SDK_INT > 26) {
|
||||
Field hardware = Bitmap.Config.class.getDeclaredField("HARDWARE");
|
||||
Field rgba_f16 = Bitmap.Config.class.getDeclaredField("RGBA_F16");
|
||||
if(hardware != null && cfg == hardware.get(null)) return PX_HARDWARE;
|
||||
if(rgba_f16 != null && cfg == rgba_f16.get(null)) return PX_RGBA_F16;
|
||||
}
|
||||
|
||||
switch (cfg) {
|
||||
case ALPHA_8:
|
||||
return PX_ALPHA;
|
||||
case ARGB_4444:
|
||||
return PX_ARGB_4444;
|
||||
case ARGB_8888:
|
||||
return PX_ARGB_8888;
|
||||
case RGB_565:
|
||||
return PX_RGB_565;
|
||||
default:
|
||||
return PX_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getFrameWidth() {
|
||||
if (mCurFrame != null) {
|
||||
return mCurFrame.getWidth();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int getFrameHeight() {
|
||||
if(mCurFrame != null) {
|
||||
return mCurFrame.getHeight();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void setShowRawFrame(boolean show) {
|
||||
if(mShowRaw == show) { // Now show state == Before show state
|
||||
return; // Do nothing
|
||||
}
|
||||
setTranslationY(0); // Show view
|
||||
if(!show) {
|
||||
setTranslationY(-1000); // Hide view
|
||||
}
|
||||
mShowRaw = show;
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// Private functions
|
||||
// ===========================================================
|
||||
|
||||
private void initVideoView() {
|
||||
mVideoWidth = 0;
|
||||
mVideoHeight = 0;
|
||||
getHolder().addCallback(mSHCallback);
|
||||
//Fix issue#11516:Can't play video on Android 2.3.x
|
||||
getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
||||
setFocusable(true);
|
||||
setFocusableInTouchMode(true);
|
||||
mCurrentState = State.IDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
private void setVideoURI(Uri uri, Map<String, String> headers) {
|
||||
mVideoUri = uri;
|
||||
mVideoWidth = 0;
|
||||
mVideoHeight = 0;
|
||||
}
|
||||
|
||||
private void openVideo() {
|
||||
if (mSurfaceHolder == null) {
|
||||
// not ready for playback just yet, will try again later
|
||||
return;
|
||||
}
|
||||
if (mIsAssetRouse) {
|
||||
if(mVideoFilePath == null)
|
||||
return;
|
||||
} else if(mVideoUri == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.pausePlaybackService();
|
||||
|
||||
try {
|
||||
mMediaPlayer = new MediaPlayer();
|
||||
mMediaPlayer.setOnPreparedListener(mPreparedListener);
|
||||
mMediaPlayer.setOnCompletionListener(mCompletionListener);
|
||||
mMediaPlayer.setOnErrorListener(mErrorListener);
|
||||
mMediaPlayer.setDisplay(mSurfaceHolder);
|
||||
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
mMediaPlayer.setScreenOnWhilePlaying(true);
|
||||
|
||||
mRetriever = new MediaMetadataRetriever();
|
||||
mFrameBuf = null;
|
||||
mPixels = null;
|
||||
mCurFrame = null;
|
||||
mFrame = null;
|
||||
|
||||
if (mIsAssetRouse) {
|
||||
AssetFileDescriptor afd = mCocos2dxActivity.getAssets().openFd(mVideoFilePath);
|
||||
mMediaPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
|
||||
mRetriever.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
|
||||
} else {
|
||||
mMediaPlayer.setDataSource(mVideoUri.toString());
|
||||
if (mVideoUri.getHost().length() > 0) {
|
||||
mRetriever.setDataSource(mVideoUri.toString(), new HashMap<String, String>());
|
||||
} else {
|
||||
mRetriever.setDataSource(mCocos2dxActivity.getContext(), mVideoUri);
|
||||
}
|
||||
}
|
||||
mCurrentState = State.INITIALIZED;
|
||||
|
||||
|
||||
// Use Prepare() instead of PrepareAsync to make things easy.
|
||||
mMediaPlayer.prepare();
|
||||
this.showFirstFrame();
|
||||
|
||||
// mMediaPlayer.prepareAsync();
|
||||
} catch (IOException ex) {
|
||||
Log.w(TAG, "Unable to open content: " + mVideoUri, ex);
|
||||
mCurrentState = State.ERROR;
|
||||
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
|
||||
return;
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Log.w(TAG, "Unable to open content: " + mVideoUri, ex);
|
||||
mCurrentState = State.ERROR;
|
||||
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
|
||||
public void onPrepared(MediaPlayer mp) {
|
||||
mVideoWidth = mp.getVideoWidth();
|
||||
mVideoHeight = mp.getVideoHeight();
|
||||
|
||||
if (mVideoWidth != 0 && mVideoHeight != 0) {
|
||||
fixSize();
|
||||
}
|
||||
|
||||
if(!mMetaUpdated) {
|
||||
Cocos2dxVideoView.this.sendEvent(EVENT_META_LOADED);
|
||||
Cocos2dxVideoView.this.sendEvent(EVENT_READY_TO_PLAY);
|
||||
mMetaUpdated = true;
|
||||
}
|
||||
|
||||
mCurrentState = State.PREPARED;
|
||||
}
|
||||
};
|
||||
|
||||
private MediaPlayer.OnCompletionListener mCompletionListener =
|
||||
new MediaPlayer.OnCompletionListener() {
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
mCurrentState = State.PLAYBACK_COMPLETED;
|
||||
Cocos2dxVideoView.this.sendEvent(EVENT_COMPLETED);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private static final int EVENT_PLAYING = 0;
|
||||
private static final int EVENT_PAUSED = 1;
|
||||
private static final int EVENT_STOPPED = 2;
|
||||
private static final int EVENT_COMPLETED = 3;
|
||||
private static final int EVENT_META_LOADED = 4;
|
||||
private static final int EVENT_CLICKED = 5;
|
||||
private static final int EVENT_READY_TO_PLAY = 6;
|
||||
|
||||
private MediaPlayer.OnErrorListener mErrorListener =
|
||||
new MediaPlayer.OnErrorListener() {
|
||||
public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
|
||||
Log.d(TAG, "Error: " + framework_err + "," + impl_err);
|
||||
mCurrentState = State.ERROR;
|
||||
|
||||
/* Otherwise, pop up an error dialog so the user knows that
|
||||
* something bad has happened. Only try and pop up the dialog
|
||||
* if we're attached to a window. When we're going away and no
|
||||
* longer have a window, don't bother showing the user an error.
|
||||
*/
|
||||
if (getWindowToken() != null) {
|
||||
Resources r = mCocos2dxActivity.getResources();
|
||||
int messageId;
|
||||
|
||||
if (framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
|
||||
// messageId = com.android.internal.R.string.VideoView_error_text_invalid_progressive_playback;
|
||||
messageId = r.getIdentifier("VideoView_error_text_invalid_progressive_playback", "string", "android");
|
||||
} else {
|
||||
// messageId = com.android.internal.R.string.VideoView_error_text_unknown;
|
||||
messageId = r.getIdentifier("VideoView_error_text_unknown", "string", "android");
|
||||
}
|
||||
|
||||
int titleId = r.getIdentifier("VideoView_error_title", "string", "android");
|
||||
int buttonStringId = r.getIdentifier("VideoView_error_button", "string", "android");
|
||||
|
||||
new AlertDialog.Builder(mCocos2dxActivity)
|
||||
.setTitle(r.getString(titleId))
|
||||
.setMessage(messageId)
|
||||
.setPositiveButton(r.getString(buttonStringId),
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
/* If we get here, there is no onError listener, so
|
||||
* at least inform them that the video is over.
|
||||
*/
|
||||
Cocos2dxVideoView.this.sendEvent(EVENT_COMPLETED);
|
||||
}
|
||||
})
|
||||
.setCancelable(false)
|
||||
.show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
|
||||
{
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
mSurfaceHolder = holder;
|
||||
Cocos2dxVideoView.this.openVideo();
|
||||
|
||||
if (mPositionBeforeRelease > 0)
|
||||
mMediaPlayer.seekTo(mPositionBeforeRelease);
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
// after we return from this we can't use the surface any more
|
||||
mSurfaceHolder = null;
|
||||
mPositionBeforeRelease = getCurrentPosition();
|
||||
Cocos2dxVideoView.this.release();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* release the media player in any state
|
||||
*/
|
||||
private void release() {
|
||||
if (mMediaPlayer != null) {
|
||||
mMediaPlayer.release();
|
||||
mMediaPlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void showFirstFrame() {
|
||||
mMediaPlayer.seekTo(1);
|
||||
}
|
||||
|
||||
private void sendEvent(int event) {
|
||||
if (this.mOnVideoEventListener != null) {
|
||||
this.mOnVideoEventListener.onVideoEvent(this.mViewTag, event);
|
||||
}
|
||||
}
|
||||
|
||||
// Tell the music playback service to pause
|
||||
// REFINE: these constants need to be published somewhere in the framework.
|
||||
private void pausePlaybackService() {
|
||||
Intent i = new Intent("com.android.music.musicservicecommand");
|
||||
i.putExtra("command", "pause");
|
||||
mCocos2dxActivity.sendBroadcast(i);
|
||||
}
|
||||
}
|
||||
174
cocos2d-x/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxWebView.java
Executable file
174
cocos2d-x/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxWebView.java
Executable file
@@ -0,0 +1,174 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
class ShouldStartLoadingWorker implements Runnable {
|
||||
private CountDownLatch mLatch;
|
||||
private boolean[] mResult;
|
||||
private final int mViewTag;
|
||||
private final String mUrlString;
|
||||
|
||||
ShouldStartLoadingWorker(CountDownLatch latch, boolean[] result, int viewTag, String urlString) {
|
||||
this.mLatch = latch;
|
||||
this.mResult = result;
|
||||
this.mViewTag = viewTag;
|
||||
this.mUrlString = urlString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.mResult[0] = Cocos2dxWebViewHelper._shouldStartLoading(mViewTag, mUrlString);
|
||||
this.mLatch.countDown(); // notify that result is ready
|
||||
}
|
||||
}
|
||||
|
||||
public class Cocos2dxWebView extends WebView {
|
||||
private static final String TAG = Cocos2dxWebViewHelper.class.getSimpleName();
|
||||
|
||||
private int mViewTag;
|
||||
private String mJSScheme;
|
||||
|
||||
public Cocos2dxWebView(Context context) {
|
||||
this(context, -1);
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
public Cocos2dxWebView(Context context, int viewTag) {
|
||||
super(context);
|
||||
this.mViewTag = viewTag;
|
||||
this.mJSScheme = "";
|
||||
|
||||
this.setFocusable(true);
|
||||
this.setFocusableInTouchMode(true);
|
||||
|
||||
this.getSettings().setSupportZoom(false);
|
||||
|
||||
this.getSettings().setDomStorageEnabled(true);
|
||||
this.getSettings().setJavaScriptEnabled(true);
|
||||
|
||||
// `searchBoxJavaBridge_` has big security risk. http://jvn.jp/en/jp/JVN53768697
|
||||
try {
|
||||
Method method = this.getClass().getMethod("removeJavascriptInterface", new Class[]{String.class});
|
||||
method.invoke(this, "searchBoxJavaBridge_");
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "This API level do not support `removeJavascriptInterface`");
|
||||
}
|
||||
|
||||
this.setWebViewClient(new Cocos2dxWebViewClient());
|
||||
this.setWebChromeClient(new WebChromeClient());
|
||||
}
|
||||
|
||||
public void setJavascriptInterfaceScheme(String scheme) {
|
||||
this.mJSScheme = scheme != null ? scheme : "";
|
||||
}
|
||||
|
||||
public void setScalesPageToFit(boolean scalesPageToFit) {
|
||||
this.getSettings().setSupportZoom(scalesPageToFit);
|
||||
}
|
||||
|
||||
class Cocos2dxWebViewClient extends WebViewClient {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, final String urlString) {
|
||||
Cocos2dxActivity activity = (Cocos2dxActivity)getContext();
|
||||
|
||||
try {
|
||||
URI uri = URI.create(urlString);
|
||||
if (uri != null && uri.getScheme().equals(mJSScheme)) {
|
||||
activity.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebViewHelper._onJsCallback(mViewTag, urlString);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "Failed to create URI from url");
|
||||
}
|
||||
|
||||
boolean[] result = new boolean[] { true };
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
// run worker on cocos thread
|
||||
activity.runOnGLThread(new ShouldStartLoadingWorker(latch, result, mViewTag, urlString));
|
||||
|
||||
// wait for result from cocos thread
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException ex) {
|
||||
Log.d(TAG, "'shouldOverrideUrlLoading' failed");
|
||||
}
|
||||
|
||||
return result[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView view, final String url) {
|
||||
super.onPageFinished(view, url);
|
||||
Cocos2dxActivity activity = (Cocos2dxActivity)getContext();
|
||||
activity.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebViewHelper._didFinishLoading(mViewTag, url);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, int errorCode, String description, final String failingUrl) {
|
||||
super.onReceivedError(view, errorCode, description, failingUrl);
|
||||
Cocos2dxActivity activity = (Cocos2dxActivity)getContext();
|
||||
activity.runOnGLThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebViewHelper._didFailLoading(mViewTag, failingUrl);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setWebViewRect(int left, int top, int maxWidth, int maxHeight) {
|
||||
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
|
||||
FrameLayout.LayoutParams.MATCH_PARENT);
|
||||
layoutParams.leftMargin = left;
|
||||
layoutParams.topMargin = top;
|
||||
layoutParams.width = maxWidth;
|
||||
layoutParams.height = maxHeight;
|
||||
this.setLayoutParams(layoutParams);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2011 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
|
||||
public class Cocos2dxWebViewHelper {
|
||||
private static final String TAG = Cocos2dxWebViewHelper.class.getSimpleName();
|
||||
private static Handler sHandler;
|
||||
private static Cocos2dxActivity sCocos2dxActivity;
|
||||
private static FrameLayout sLayout;
|
||||
|
||||
private static SparseArray<Cocos2dxWebView> webViews;
|
||||
private static int viewTag = 0;
|
||||
|
||||
public Cocos2dxWebViewHelper(FrameLayout layout) {
|
||||
Cocos2dxWebViewHelper.sLayout = layout;
|
||||
Cocos2dxWebViewHelper.sHandler = new Handler(Looper.myLooper());
|
||||
|
||||
Cocos2dxWebViewHelper.sCocos2dxActivity = (Cocos2dxActivity) Cocos2dxActivity.getContext();
|
||||
Cocos2dxWebViewHelper.webViews = new SparseArray<Cocos2dxWebView>();
|
||||
}
|
||||
|
||||
private static native boolean shouldStartLoading(int index, String message);
|
||||
|
||||
public static boolean _shouldStartLoading(int index, String message) {
|
||||
return !shouldStartLoading(index, message);
|
||||
}
|
||||
|
||||
private static native void didFinishLoading(int index, String message);
|
||||
|
||||
public static void _didFinishLoading(int index, String message) {
|
||||
didFinishLoading(index, message);
|
||||
}
|
||||
|
||||
private static native void didFailLoading(int index, String message);
|
||||
|
||||
public static void _didFailLoading(int index, String message) {
|
||||
didFailLoading(index, message);
|
||||
}
|
||||
|
||||
private static native void onJsCallback(int index, String message);
|
||||
|
||||
public static void _onJsCallback(int index, String message) {
|
||||
onJsCallback(index, message);
|
||||
}
|
||||
|
||||
public static int createWebView() {
|
||||
final int index = viewTag;
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = new Cocos2dxWebView(sCocos2dxActivity, index);
|
||||
FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT);
|
||||
sLayout.addView(webView, lParams);
|
||||
|
||||
webViews.put(index, webView);
|
||||
}
|
||||
});
|
||||
return viewTag++;
|
||||
}
|
||||
|
||||
public static void removeWebView(final int index) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webViews.remove(index);
|
||||
sLayout.removeView(webView);
|
||||
webView.destroy();
|
||||
webView = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setVisible(final int index, final boolean visible) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setWebViewRect(final int index, final int left, final int top, final int maxWidth, final int maxHeight) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.setWebViewRect(left, top, maxWidth, maxHeight);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setBackgroundTransparent(final int index, final boolean isTransparent) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.setBackgroundColor(isTransparent ? Color.TRANSPARENT : Color.WHITE);
|
||||
webView.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setJavascriptInterfaceScheme(final int index, final String scheme) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.setJavascriptInterfaceScheme(scheme);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void loadData(final int index, final String data, final String mimeType, final String encoding, final String baseURL) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.loadDataWithBaseURL(baseURL, data, mimeType, encoding, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void loadHTMLString(final int index, final String data, final String baseUrl) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.loadDataWithBaseURL(baseUrl, data, null, null, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void loadUrl(final int index, final String url) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.loadUrl(url);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void loadFile(final int index, final String filePath) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.loadUrl(filePath);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void stopLoading(final int index) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.stopLoading();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public static void reload(final int index) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static <T> T callInMainThread(Callable<T> call) throws ExecutionException, InterruptedException {
|
||||
FutureTask<T> task = new FutureTask<T>(call);
|
||||
sHandler.post(task);
|
||||
return task.get();
|
||||
}
|
||||
|
||||
public static boolean canGoBack(final int index) {
|
||||
Callable<Boolean> callable = new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
return webView != null && webView.canGoBack();
|
||||
}
|
||||
};
|
||||
try {
|
||||
return callInMainThread(callable);
|
||||
} catch (ExecutionException e) {
|
||||
return false;
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean canGoForward(final int index) {
|
||||
Callable<Boolean> callable = new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
return webView != null && webView.canGoForward();
|
||||
}
|
||||
};
|
||||
try {
|
||||
return callInMainThread(callable);
|
||||
} catch (ExecutionException e) {
|
||||
return false;
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void goBack(final int index) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.goBack();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void goForward(final int index) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.goForward();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void evaluateJS(final int index, final String js) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.loadUrl("javascript:" + js);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setScalesPageToFit(final int index, final boolean scalesPageToFit) {
|
||||
sCocos2dxActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Cocos2dxWebView webView = webViews.get(index);
|
||||
if (webView != null) {
|
||||
webView.setScalesPageToFit(scalesPageToFit);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
|
||||
public class Utils {
|
||||
private static Activity sActivity = null;
|
||||
|
||||
public static void setActivity(final Activity activity) {
|
||||
Utils.sActivity = activity;
|
||||
}
|
||||
|
||||
public static void hideVirtualButton() {
|
||||
if (Build.VERSION.SDK_INT >= 19 &&
|
||||
null != Utils.sActivity) {
|
||||
// use reflection to remove dependence of API level
|
||||
|
||||
Class viewClass = View.class;
|
||||
final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = Cocos2dxReflectionHelper.<Integer>getConstantValue(viewClass, "SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION");
|
||||
final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = Cocos2dxReflectionHelper.<Integer>getConstantValue(viewClass, "SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN");
|
||||
final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = Cocos2dxReflectionHelper.<Integer>getConstantValue(viewClass, "SYSTEM_UI_FLAG_HIDE_NAVIGATION");
|
||||
final int SYSTEM_UI_FLAG_FULLSCREEN = Cocos2dxReflectionHelper.<Integer>getConstantValue(viewClass, "SYSTEM_UI_FLAG_FULLSCREEN");
|
||||
final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = Cocos2dxReflectionHelper.<Integer>getConstantValue(viewClass, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY");
|
||||
final int SYSTEM_UI_FLAG_LAYOUT_STABLE = Cocos2dxReflectionHelper.<Integer>getConstantValue(viewClass, "SYSTEM_UI_FLAG_LAYOUT_STABLE");
|
||||
|
||||
// getWindow().getDecorView().setSystemUiVisibility();
|
||||
final Object[] parameters = new Object[]{SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
|
||||
| SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
|
||||
| SYSTEM_UI_FLAG_IMMERSIVE_STICKY};
|
||||
Cocos2dxReflectionHelper.<Void>invokeInstanceMethod(Utils.sActivity.getWindow().getDecorView(),
|
||||
"setSystemUiVisibility",
|
||||
new Class[]{Integer.TYPE},
|
||||
parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
319
cocos2d-x/cocos/platform/android/jni/JniHelper.cpp
Normal file
319
cocos2d-x/cocos/platform/android/jni/JniHelper.cpp
Normal file
@@ -0,0 +1,319 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "platform/android/jni/JniHelper.h"
|
||||
#include <android/log.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "base/ccUTF8.h"
|
||||
|
||||
#define LOG_TAG "JniHelper"
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
|
||||
|
||||
static pthread_key_t g_key;
|
||||
|
||||
jclass _getClassID(const char *className) {
|
||||
if (nullptr == className) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JNIEnv* env = cocos2d::JniHelper::getEnv();
|
||||
|
||||
jstring _jstrClassName = env->NewStringUTF(className);
|
||||
|
||||
jclass _clazz = (jclass) env->CallObjectMethod(cocos2d::JniHelper::classloader,
|
||||
cocos2d::JniHelper::loadclassMethod_methodID,
|
||||
_jstrClassName);
|
||||
|
||||
if (nullptr == _clazz || env->ExceptionCheck()) {
|
||||
LOGE("Classloader failed to find class of %s", className);
|
||||
env->ExceptionClear();
|
||||
_clazz = nullptr;
|
||||
}
|
||||
|
||||
env->DeleteLocalRef(_jstrClassName);
|
||||
|
||||
return _clazz;
|
||||
}
|
||||
|
||||
void _detachCurrentThread(void* a) {
|
||||
cocos2d::JniHelper::getJavaVM()->DetachCurrentThread();
|
||||
}
|
||||
|
||||
namespace cocos2d {
|
||||
|
||||
JavaVM* JniHelper::_psJavaVM = nullptr;
|
||||
jmethodID JniHelper::loadclassMethod_methodID = nullptr;
|
||||
jobject JniHelper::classloader = nullptr;
|
||||
std::function<void()> JniHelper::classloaderCallback = nullptr;
|
||||
|
||||
jobject JniHelper::_activity = nullptr;
|
||||
|
||||
JavaVM* JniHelper::getJavaVM() {
|
||||
pthread_t thisthread = pthread_self();
|
||||
LOGD("JniHelper::getJavaVM(), pthread_self() = %ld", thisthread);
|
||||
return _psJavaVM;
|
||||
}
|
||||
|
||||
void JniHelper::setJavaVM(JavaVM *javaVM) {
|
||||
pthread_t thisthread = pthread_self();
|
||||
LOGD("JniHelper::setJavaVM(%p), pthread_self() = %ld", javaVM, thisthread);
|
||||
_psJavaVM = javaVM;
|
||||
|
||||
pthread_key_create(&g_key, _detachCurrentThread);
|
||||
}
|
||||
|
||||
JNIEnv* JniHelper::cacheEnv(JavaVM* jvm) {
|
||||
JNIEnv* _env = nullptr;
|
||||
// get jni environment
|
||||
jint ret = jvm->GetEnv((void**)&_env, JNI_VERSION_1_4);
|
||||
|
||||
switch (ret) {
|
||||
case JNI_OK :
|
||||
// Success!
|
||||
pthread_setspecific(g_key, _env);
|
||||
return _env;
|
||||
|
||||
case JNI_EDETACHED :
|
||||
// Thread not attached
|
||||
if (jvm->AttachCurrentThread(&_env, nullptr) < 0)
|
||||
{
|
||||
LOGE("Failed to get the environment using AttachCurrentThread()");
|
||||
|
||||
return nullptr;
|
||||
} else {
|
||||
// Success : Attached and obtained JNIEnv!
|
||||
pthread_setspecific(g_key, _env);
|
||||
return _env;
|
||||
}
|
||||
|
||||
case JNI_EVERSION :
|
||||
// Cannot recover from this error
|
||||
LOGE("JNI interface version 1.4 not supported");
|
||||
default :
|
||||
LOGE("Failed to get the environment using GetEnv()");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEnv* JniHelper::getEnv() {
|
||||
JNIEnv *_env = (JNIEnv *)pthread_getspecific(g_key);
|
||||
if (_env == nullptr)
|
||||
_env = JniHelper::cacheEnv(_psJavaVM);
|
||||
return _env;
|
||||
}
|
||||
|
||||
jobject JniHelper::getActivity() {
|
||||
return _activity;
|
||||
}
|
||||
|
||||
bool JniHelper::setClassLoaderFrom(jobject activityinstance) {
|
||||
JniMethodInfo _getclassloaderMethod;
|
||||
if (!JniHelper::getMethodInfo_DefaultClassLoader(_getclassloaderMethod,
|
||||
"android/content/Context",
|
||||
"getClassLoader",
|
||||
"()Ljava/lang/ClassLoader;")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jobject _c = cocos2d::JniHelper::getEnv()->CallObjectMethod(activityinstance,
|
||||
_getclassloaderMethod.methodID);
|
||||
|
||||
if (nullptr == _c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JniMethodInfo _m;
|
||||
if (!JniHelper::getMethodInfo_DefaultClassLoader(_m,
|
||||
"java/lang/ClassLoader",
|
||||
"loadClass",
|
||||
"(Ljava/lang/String;)Ljava/lang/Class;")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JniHelper::classloader = cocos2d::JniHelper::getEnv()->NewGlobalRef(_c);
|
||||
JniHelper::loadclassMethod_methodID = _m.methodID;
|
||||
JniHelper::_activity = cocos2d::JniHelper::getEnv()->NewGlobalRef(activityinstance);
|
||||
if (JniHelper::classloaderCallback != nullptr){
|
||||
JniHelper::classloaderCallback();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JniHelper::getStaticMethodInfo(JniMethodInfo &methodinfo,
|
||||
const char *className,
|
||||
const char *methodName,
|
||||
const char *paramCode) {
|
||||
if ((nullptr == className) ||
|
||||
(nullptr == methodName) ||
|
||||
(nullptr == paramCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JNIEnv *env = JniHelper::getEnv();
|
||||
if (!env) {
|
||||
LOGE("Failed to get JNIEnv");
|
||||
return false;
|
||||
}
|
||||
|
||||
jclass classID = _getClassID(className);
|
||||
if (! classID) {
|
||||
LOGE("Failed to find class %s", className);
|
||||
env->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
|
||||
jmethodID methodID = env->GetStaticMethodID(classID, methodName, paramCode);
|
||||
if (! methodID) {
|
||||
LOGE("Failed to find static method id of %s", methodName);
|
||||
env->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
|
||||
methodinfo.classID = classID;
|
||||
methodinfo.env = env;
|
||||
methodinfo.methodID = methodID;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JniHelper::getMethodInfo_DefaultClassLoader(JniMethodInfo &methodinfo,
|
||||
const char *className,
|
||||
const char *methodName,
|
||||
const char *paramCode) {
|
||||
if ((nullptr == className) ||
|
||||
(nullptr == methodName) ||
|
||||
(nullptr == paramCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JNIEnv *env = JniHelper::getEnv();
|
||||
if (!env) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jclass classID = env->FindClass(className);
|
||||
if (! classID) {
|
||||
LOGE("Failed to find class %s", className);
|
||||
env->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
|
||||
jmethodID methodID = env->GetMethodID(classID, methodName, paramCode);
|
||||
if (! methodID) {
|
||||
LOGE("Failed to find method id of %s", methodName);
|
||||
env->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
|
||||
methodinfo.classID = classID;
|
||||
methodinfo.env = env;
|
||||
methodinfo.methodID = methodID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JniHelper::getMethodInfo(JniMethodInfo &methodinfo,
|
||||
const char *className,
|
||||
const char *methodName,
|
||||
const char *paramCode) {
|
||||
if ((nullptr == className) ||
|
||||
(nullptr == methodName) ||
|
||||
(nullptr == paramCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JNIEnv *env = JniHelper::getEnv();
|
||||
if (!env) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jclass classID = _getClassID(className);
|
||||
if (! classID) {
|
||||
LOGE("Failed to find class %s", className);
|
||||
env->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
|
||||
jmethodID methodID = env->GetMethodID(classID, methodName, paramCode);
|
||||
if (! methodID) {
|
||||
LOGE("Failed to find method id of %s", methodName);
|
||||
env->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
|
||||
methodinfo.classID = classID;
|
||||
methodinfo.env = env;
|
||||
methodinfo.methodID = methodID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string JniHelper::jstring2string(jstring jstr) {
|
||||
if (jstr == nullptr) {
|
||||
return "";
|
||||
}
|
||||
|
||||
JNIEnv *env = JniHelper::getEnv();
|
||||
if (!env) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string strValue = cocos2d::StringUtils::getStringUTFCharsJNI(env, jstr);
|
||||
|
||||
return strValue;
|
||||
}
|
||||
|
||||
jstring JniHelper::convert(JniHelper::LocalRefMapType &localRefs, cocos2d::JniMethodInfo& t, const char* x) {
|
||||
jstring ret = nullptr;
|
||||
if (x)
|
||||
ret = cocos2d::StringUtils::newStringUTFJNI(t.env, x);
|
||||
|
||||
localRefs[t.env].push_back(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
jstring JniHelper::convert(JniHelper::LocalRefMapType &localRefs, cocos2d::JniMethodInfo& t, const std::string& x) {
|
||||
return convert(localRefs, t, x.c_str());
|
||||
}
|
||||
|
||||
void JniHelper::deleteLocalRefs(JNIEnv* env, JniHelper::LocalRefMapType &localRefs) {
|
||||
if (!env) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& ref : localRefs[env]) {
|
||||
env->DeleteLocalRef(ref);
|
||||
}
|
||||
localRefs[env].clear();
|
||||
}
|
||||
|
||||
void JniHelper::reportError(const std::string& className, const std::string& methodName, const std::string& signature) {
|
||||
LOGE("Failed to find static java method. Class name: %s, method name: %s, signature: %s ", className.c_str(), methodName.c_str(), signature.c_str());
|
||||
}
|
||||
|
||||
} //namespace cocos2d
|
||||
399
cocos2d-x/cocos/platform/android/jni/JniHelper.h
Normal file
399
cocos2d-x/cocos/platform/android/jni/JniHelper.h
Normal file
@@ -0,0 +1,399 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#ifndef __ANDROID_JNI_HELPER_H__
|
||||
#define __ANDROID_JNI_HELPER_H__
|
||||
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
#include "base/ccMacros.h"
|
||||
#include "math/Vec3.h"
|
||||
|
||||
//The macro must be used this way to find the native method. The principle is not well understood.
|
||||
#define JNI_METHOD2(CLASS2,FUNC2) Java_##CLASS2##_##FUNC2
|
||||
#define JNI_METHOD1(CLASS1,FUNC1) JNI_METHOD2(CLASS1,FUNC1)
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
typedef struct JniMethodInfo_
|
||||
{
|
||||
JNIEnv * env;
|
||||
jclass classID;
|
||||
jmethodID methodID;
|
||||
} JniMethodInfo;
|
||||
|
||||
|
||||
class CC_DLL JniHelper
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::unordered_map<JNIEnv *, std::vector<jobject >> LocalRefMapType;
|
||||
|
||||
static void setJavaVM(JavaVM *javaVM);
|
||||
static JavaVM* getJavaVM();
|
||||
static JNIEnv* getEnv();
|
||||
static jobject getActivity();
|
||||
|
||||
static bool setClassLoaderFrom(jobject activityInstance);
|
||||
static bool getStaticMethodInfo(JniMethodInfo &methodinfo,
|
||||
const char *className,
|
||||
const char *methodName,
|
||||
const char *paramCode);
|
||||
static bool getMethodInfo(JniMethodInfo &methodinfo,
|
||||
const char *className,
|
||||
const char *methodName,
|
||||
const char *paramCode);
|
||||
|
||||
static std::string jstring2string(jstring str);
|
||||
|
||||
static jmethodID loadclassMethod_methodID;
|
||||
static jobject classloader;
|
||||
static std::function<void()> classloaderCallback;
|
||||
|
||||
template <typename... Ts>
|
||||
static jobject newObject(const std::string& className, Ts... xs)
|
||||
{
|
||||
jobject ret = nullptr;
|
||||
static const char* methodName = "<init>";
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")V";
|
||||
if (cocos2d::JniHelper::getMethodInfo(t, className.c_str(), methodName, signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
ret = t.env->NewObject(t.classID, t.methodID, convert(t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static void callObjectVoidMethod(jobject object,
|
||||
const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")V";
|
||||
if (cocos2d::JniHelper::getMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
t.env->CallVoidMethod(object, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static float callObjectFloatMethod(jobject object,
|
||||
const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
float ret = 0.0f;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")F";
|
||||
if (cocos2d::JniHelper::getMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
ret = t.env->CallFloatMethod(object, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static jbyteArray callObjectByteArrayMethod(jobject object,
|
||||
const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
jbyteArray ret = nullptr;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")[B";
|
||||
if (cocos2d::JniHelper::getMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
ret = (jbyteArray)t.env->CallObjectMethod(object, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static void callStaticVoidMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")V";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
t.env->CallStaticVoidMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static bool callStaticBooleanMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
jboolean jret = JNI_FALSE;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")Z";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
jret = t.env->CallStaticBooleanMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return (jret == JNI_TRUE);
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static int callStaticIntMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
jint ret = 0;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")I";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
ret = t.env->CallStaticIntMethod(t.classID, t.methodID, convert(t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static float callStaticFloatMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
jfloat ret = 0.0;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")F";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
ret = t.env->CallStaticFloatMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static float* callStaticFloatArrayMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
static float ret[32];
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")[F";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
jfloatArray array = (jfloatArray) t.env->CallStaticObjectMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
jsize len = t.env->GetArrayLength(array);
|
||||
if (len <= 32) {
|
||||
jfloat* elems = t.env->GetFloatArrayElements(array, 0);
|
||||
if (elems) {
|
||||
memcpy(ret, elems, sizeof(float) * len);
|
||||
t.env->ReleaseFloatArrayElements(array, elems, 0);
|
||||
};
|
||||
}
|
||||
t.env->DeleteLocalRef(array);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
return &ret[0];
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static Vec3 callStaticVec3Method(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
Vec3 ret;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")[F";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
jfloatArray array = (jfloatArray) t.env->CallStaticObjectMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
jsize len = t.env->GetArrayLength(array);
|
||||
if (len == 3) {
|
||||
jfloat* elems = t.env->GetFloatArrayElements(array, 0);
|
||||
ret.x = elems[0];
|
||||
ret.y = elems[1];
|
||||
ret.z = elems[2];
|
||||
t.env->ReleaseFloatArrayElements(array, elems, 0);
|
||||
}
|
||||
t.env->DeleteLocalRef(array);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static double callStaticDoubleMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
jdouble ret = 0.0;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")D";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
ret = t.env->CallStaticDoubleMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static std::string callStaticStringMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
std::string ret;
|
||||
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")Ljava/lang/String;";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
jstring jret = (jstring)t.env->CallStaticObjectMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
ret = cocos2d::JniHelper::jstring2string(jret);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
t.env->DeleteLocalRef(jret);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
static JNIEnv* cacheEnv(JavaVM* jvm);
|
||||
|
||||
static bool getMethodInfo_DefaultClassLoader(JniMethodInfo &methodinfo,
|
||||
const char *className,
|
||||
const char *methodName,
|
||||
const char *paramCode);
|
||||
|
||||
static JavaVM* _psJavaVM;
|
||||
|
||||
static jobject _activity;
|
||||
|
||||
static jstring convert(LocalRefMapType &localRefs, cocos2d::JniMethodInfo& t, const char* x);
|
||||
|
||||
static jstring convert(LocalRefMapType &localRefs, cocos2d::JniMethodInfo& t, const std::string& x);
|
||||
|
||||
template <typename T>
|
||||
static T convert(LocalRefMapType &localRefs, cocos2d::JniMethodInfo&, T x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
static void deleteLocalRefs(JNIEnv* env, LocalRefMapType &localRefs);
|
||||
|
||||
static std::string getJNISignature() {
|
||||
return "";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(bool) {
|
||||
return "Z";
|
||||
}
|
||||
|
||||
// jchar is unsigned 16 bits, we do char => jchar conversion on purpose
|
||||
static std::string getJNISignature(char) {
|
||||
return "C";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(jshort) {
|
||||
return "S";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(jint) {
|
||||
return "I";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(jlong) {
|
||||
return "J";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(jfloat) {
|
||||
return "F";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(jdouble) {
|
||||
return "D";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(jbyteArray) {
|
||||
return "[B";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(const char*) {
|
||||
return "Ljava/lang/String;";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(const std::string&) {
|
||||
return "Ljava/lang/String;";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static std::string getJNISignature(T x) {
|
||||
// This template should never be instantiated
|
||||
static_assert(sizeof(x) == 0, "Unsupported argument type");
|
||||
return "";
|
||||
}
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
static std::string getJNISignature(T x, Ts... xs) {
|
||||
return getJNISignature(x) + getJNISignature(xs...);
|
||||
}
|
||||
|
||||
static void reportError(const std::string& className, const std::string& methodName, const std::string& signature);
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // __ANDROID_JNI_HELPER_H__
|
||||
680
cocos2d-x/cocos/platform/android/jni/JniImp.cpp
Normal file
680
cocos2d-x/cocos/platform/android/jni/JniImp.cpp
Normal file
@@ -0,0 +1,680 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "JniImp.h"
|
||||
#include <unordered_map>
|
||||
#include <android/log.h>
|
||||
#include <android/asset_manager_jni.h>
|
||||
#include <jni.h>
|
||||
#include <mutex>
|
||||
#include "JniHelper.h"
|
||||
#include "platform/CCApplication.h"
|
||||
#include "scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "scripting/js-bindings/event/EventDispatcher.h"
|
||||
#include "platform/android/CCFileUtils-android.h"
|
||||
#include "base/CCScheduler.h"
|
||||
#include "base/CCAutoreleasePool.h"
|
||||
#include "base/CCGLUtils.h"
|
||||
|
||||
#define JNI_IMP_LOG_TAG "JniImp"
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,JNI_IMP_LOG_TAG,__VA_ARGS__)
|
||||
|
||||
#ifndef ORG_RENDER_CLASS_NAME
|
||||
#define ORG_RENDER_CLASS_NAME org_cocos2dx_lib_Cocos2dxRenderer
|
||||
#endif
|
||||
#define JNI_RENDER(FUNC) JNI_METHOD1(ORG_RENDER_CLASS_NAME,FUNC)
|
||||
|
||||
#ifndef ORG_ACTIVITY_CLASS_NAME
|
||||
#define ORG_ACTIVITY_CLASS_NAME org_cocos2dx_lib_Cocos2dxActivity
|
||||
#endif
|
||||
#define JNI_ACTIVITY(FUNC) JNI_METHOD1(ORG_ACTIVITY_CLASS_NAME,FUNC)
|
||||
|
||||
#ifndef ORG_ACCELEROMETER_CLASS_NAME
|
||||
#define ORG_ACCELEROMETER_CLASS_NAME org_cocos2dx_lib_Cocos2dxAccelerometer
|
||||
#endif
|
||||
#define JNI_ACCELEROMETER(FUNC) JNI_METHOD1(ORG_ACCELEROMETER_CLASS_NAME,FUNC)
|
||||
|
||||
#ifndef ORG_HELPER_CLASS_NAME
|
||||
#define ORG_HELPER_CLASS_NAME org_cocos2dx_lib_Cocos2dxHelper
|
||||
#endif
|
||||
#define JNI_HELPER(FUNC) JNI_METHOD1(ORG_HELPER_CLASS_NAME,FUNC)
|
||||
|
||||
#ifndef ORG_AUDIOFOCUS_CLASS_NAME
|
||||
#define ORG_AUDIOFOCUS_CLASS_NAME org_cocos2dx_lib_Cocos2dxAudioFocusManager
|
||||
#endif
|
||||
#define JNI_AUDIO(FUNC) JNI_METHOD1(ORG_AUDIOFOCUS_CLASS_NAME,FUNC)
|
||||
|
||||
#ifndef JCLS_HELPER
|
||||
#define JCLS_HELPER "org/cocos2dx/lib/Cocos2dxHelper"
|
||||
#endif
|
||||
|
||||
#ifndef JCLS_RENDERER
|
||||
#define JCLS_RENDERER "org/cocos2dx/lib/Cocos2dxRenderer"
|
||||
#endif
|
||||
|
||||
|
||||
#define KEYCODE_BACK 0x04
|
||||
#define KEYCODE_MENU 0x52
|
||||
#define KEYCODE_DPAD_UP 0x13
|
||||
#define KEYCODE_DPAD_DOWN 0x14
|
||||
#define KEYCODE_DPAD_LEFT 0x15
|
||||
#define KEYCODE_DPAD_RIGHT 0x16
|
||||
#define KEYCODE_ENTER 0x42
|
||||
#define KEYCODE_DPAD_CENTER 0x17
|
||||
|
||||
using namespace cocos2d;
|
||||
|
||||
extern uint32_t __jsbInvocationCount;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
bool __isOpenDebugView = false;
|
||||
bool __isGLOptModeEnabled = true;
|
||||
std::string g_apkPath;
|
||||
EditTextCallback s_editTextCallback = nullptr;
|
||||
void* s_ctx = nullptr;
|
||||
int g_deviceSampleRate = 44100;
|
||||
int g_deviceAudioBufferSizeInFrames = 192;
|
||||
int g_width = 0;
|
||||
int g_height = 0;
|
||||
bool g_isStarted = false;
|
||||
bool g_isGameFinished = false;
|
||||
int g_SDKInt = 0;
|
||||
|
||||
cocos2d::Application* g_app = nullptr;
|
||||
|
||||
bool setCanvasCallback(se::Object* global)
|
||||
{
|
||||
se::AutoHandleScope scope;
|
||||
se::ScriptEngine* se = se::ScriptEngine::getInstance();
|
||||
char commandBuf[200] = {0};
|
||||
uint8_t devicePixelRatio = Application::getInstance()->getDevicePixelRatio();
|
||||
sprintf(commandBuf, "window.innerWidth = %d; window.innerHeight = %d;",
|
||||
g_width / devicePixelRatio,
|
||||
g_height / devicePixelRatio);
|
||||
se->evalString(commandBuf);
|
||||
glViewport(0, 0, g_width / devicePixelRatio, g_height / devicePixelRatio);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void cocos_jni_env_init (JNIEnv* env);
|
||||
|
||||
Application* cocos_android_app_init(JNIEnv* env, int width, int height);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void getSDKInt(JNIEnv* env)
|
||||
{
|
||||
if (env && g_SDKInt == 0)
|
||||
{
|
||||
// VERSION is a nested class within android.os.Build (hence "$" rather than "/")
|
||||
jclass versionClass = env->FindClass("android/os/Build$VERSION");
|
||||
if (NULL == versionClass)
|
||||
return;
|
||||
|
||||
jfieldID sdkIntFieldID = env->GetStaticFieldID(versionClass, "SDK_INT", "I");
|
||||
if (NULL == sdkIntFieldID)
|
||||
return;
|
||||
|
||||
g_SDKInt = env->GetStaticIntField(versionClass, sdkIntFieldID);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved)
|
||||
{
|
||||
JniHelper::setJavaVM(vm);
|
||||
cocos_jni_env_init(JniHelper::getEnv());
|
||||
getSDKInt(JniHelper::getEnv());
|
||||
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* Cocos2dxActivity native functions implementation.
|
||||
*****************************************************/
|
||||
|
||||
JNIEXPORT jintArray JNICALL JNI_ACTIVITY(getGLContextAttrs)(JNIEnv* env, jobject thiz)
|
||||
{
|
||||
//REFINE
|
||||
int tmp[7] = {8, 8, 8,
|
||||
8, 0, 0, 0};
|
||||
jintArray glContextAttrsJava = env->NewIntArray(7);
|
||||
env->SetIntArrayRegion(glContextAttrsJava, 0, 7, tmp);
|
||||
|
||||
return glContextAttrsJava;
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* Cocos2dxRenderer native functions implementation.
|
||||
*****************************************************/
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeInit)(JNIEnv* env, jobject thiz, jint w, jint h, jstring jDefaultResourcePath)
|
||||
{
|
||||
g_width = w;
|
||||
g_height = h;
|
||||
|
||||
g_app = cocos_android_app_init(env, w, h);
|
||||
|
||||
g_isGameFinished = false;
|
||||
ccInvalidateStateCache();
|
||||
std::string defaultResourcePath = JniHelper::jstring2string(jDefaultResourcePath);
|
||||
LOGD("nativeInit: %d, %d, %s", w, h, defaultResourcePath.c_str());
|
||||
|
||||
|
||||
if (!defaultResourcePath.empty())
|
||||
FileUtils::getInstance()->setDefaultResourceRootPath(defaultResourcePath);
|
||||
|
||||
se::ScriptEngine* se = se::ScriptEngine::getInstance();
|
||||
se->addRegisterCallback(setCanvasCallback);
|
||||
|
||||
EventDispatcher::init();
|
||||
|
||||
g_app->start();
|
||||
g_isStarted = true;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeRender)(JNIEnv* env)
|
||||
{
|
||||
if (g_isGameFinished)
|
||||
{
|
||||
// with Application destructor called, native resource will be released
|
||||
delete g_app;
|
||||
g_app = nullptr;
|
||||
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "endApplication");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!g_isStarted)
|
||||
{
|
||||
auto scheduler = Application::getInstance()->getScheduler();
|
||||
scheduler->removeAllFunctionsToBePerformedInCocosThread();
|
||||
scheduler->unscheduleAll();
|
||||
|
||||
se::ScriptEngine::getInstance()->cleanup();
|
||||
cocos2d::PoolManager::getInstance()->getCurrentPool()->clear();
|
||||
|
||||
//REFINE: Wait HttpClient, WebSocket, Audio thread to exit
|
||||
|
||||
ccInvalidateStateCache();
|
||||
|
||||
se::ScriptEngine* se = se::ScriptEngine::getInstance();
|
||||
se->addRegisterCallback(setCanvasCallback);
|
||||
|
||||
EventDispatcher::init();
|
||||
|
||||
if(!g_app->applicationDidFinishLaunching())
|
||||
{
|
||||
g_isGameFinished = true;
|
||||
return;
|
||||
}
|
||||
|
||||
g_isStarted = true;
|
||||
}
|
||||
|
||||
static std::chrono::steady_clock::time_point prevTime;
|
||||
static std::chrono::steady_clock::time_point now;
|
||||
static float dt = 0.f;
|
||||
static float dtSum = 0.f;
|
||||
static uint32_t jsbInvocationTotalCount = 0;
|
||||
static uint32_t jsbInvocationTotalFrames = 0;
|
||||
bool downsampleEnabled = g_app->isDownsampleEnabled();
|
||||
|
||||
if (downsampleEnabled)
|
||||
g_app->getRenderTexture()->prepare();
|
||||
|
||||
g_app->getScheduler()->update(dt);
|
||||
EventDispatcher::dispatchTickEvent(dt);
|
||||
|
||||
if (downsampleEnabled)
|
||||
g_app->getRenderTexture()->draw();
|
||||
|
||||
PoolManager::getInstance()->getCurrentPool()->clear();
|
||||
|
||||
now = std::chrono::steady_clock::now();
|
||||
dt = std::chrono::duration_cast<std::chrono::microseconds>(now - prevTime).count() / 1000000.f;
|
||||
|
||||
prevTime = std::chrono::steady_clock::now();
|
||||
|
||||
if (__isOpenDebugView)
|
||||
{
|
||||
dtSum += dt;
|
||||
++jsbInvocationTotalFrames;
|
||||
jsbInvocationTotalCount += __jsbInvocationCount;
|
||||
|
||||
if (dtSum > 1.0f)
|
||||
{
|
||||
dtSum = 0.0f;
|
||||
setJSBInvocationCountJNI(jsbInvocationTotalCount / jsbInvocationTotalFrames);
|
||||
jsbInvocationTotalCount = 0;
|
||||
jsbInvocationTotalFrames = 0;
|
||||
}
|
||||
}
|
||||
__jsbInvocationCount = 0;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeOnPause)()
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
if (g_app)
|
||||
g_app->onPause();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeOnResume)()
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
if (g_app)
|
||||
g_app->onResume();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeInsertText)(JNIEnv* env, jobject thiz, jstring text)
|
||||
{
|
||||
//REFINE
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeDeleteBackward)(JNIEnv* env, jobject thiz)
|
||||
{
|
||||
//REFINE
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL JNI_RENDER(nativeGetContentText)()
|
||||
{
|
||||
//REFINE
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeOnSurfaceChanged)(JNIEnv* env, jobject thiz, jint w, jint h)
|
||||
{
|
||||
//REFINE
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Cocos2dxAccelerometer native functions implementation.
|
||||
***********************************************************/
|
||||
|
||||
JNIEXPORT void JNICALL JNI_ACCELEROMETER(onSensorChanged)(JNIEnv* env, jobject thiz, jfloat x, jfloat y, jfloat z, jlong timeStamp)
|
||||
{
|
||||
//REFINE
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Touches native functions implementation.
|
||||
***********************************************************/
|
||||
|
||||
static void dispatchTouchEventWithOnePoint(JNIEnv* env, cocos2d::TouchEvent::Type type, jint id, jfloat x, jfloat y)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
cocos2d::TouchEvent touchEvent;
|
||||
touchEvent.type = type;
|
||||
|
||||
uint8_t devicePixelRatio = Application::getInstance()->getDevicePixelRatio();
|
||||
cocos2d::TouchInfo touchInfo;
|
||||
touchInfo.index = id;
|
||||
touchInfo.x = x / devicePixelRatio;
|
||||
touchInfo.y = y / devicePixelRatio;
|
||||
touchEvent.touches.push_back(touchInfo);
|
||||
|
||||
cocos2d::EventDispatcher::dispatchTouchEvent(touchEvent);
|
||||
}
|
||||
|
||||
static void dispatchTouchEventWithPoints(JNIEnv* env, cocos2d::TouchEvent::Type type, jintArray ids, jfloatArray xs, jfloatArray ys)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
cocos2d::TouchEvent touchEvent;
|
||||
touchEvent.type = type;
|
||||
|
||||
int size = env->GetArrayLength(ids);
|
||||
jint id[size];
|
||||
jfloat x[size];
|
||||
jfloat y[size];
|
||||
|
||||
env->GetIntArrayRegion(ids, 0, size, id);
|
||||
env->GetFloatArrayRegion(xs, 0, size, x);
|
||||
env->GetFloatArrayRegion(ys, 0, size, y);
|
||||
|
||||
uint8_t devicePixelRatio = Application::getInstance()->getDevicePixelRatio();
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
cocos2d::TouchInfo touchInfo;
|
||||
touchInfo.index = id[i];
|
||||
touchInfo.x = x[i] / devicePixelRatio;
|
||||
touchInfo.y = y[i] / devicePixelRatio;
|
||||
touchEvent.touches.push_back(touchInfo);
|
||||
}
|
||||
|
||||
cocos2d::EventDispatcher::dispatchTouchEvent(touchEvent);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeTouchesBegin)(JNIEnv * env, jobject thiz, jint id, jfloat x, jfloat y)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
dispatchTouchEventWithOnePoint(env, cocos2d::TouchEvent::Type::BEGAN, id, x, y);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeTouchesEnd)(JNIEnv * env, jobject thiz, jint id, jfloat x, jfloat y)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
dispatchTouchEventWithOnePoint(env, cocos2d::TouchEvent::Type::ENDED, id, x, y);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeTouchesMove)(JNIEnv * env, jobject thiz, jintArray ids, jfloatArray xs, jfloatArray ys)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
dispatchTouchEventWithPoints(env, cocos2d::TouchEvent::Type::MOVED, ids, xs, ys);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeTouchesCancel)(JNIEnv * env, jobject thiz, jintArray ids, jfloatArray xs, jfloatArray ys)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
dispatchTouchEventWithPoints(env, cocos2d::TouchEvent::Type::CANCELLED, ids, xs, ys);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL JNI_RENDER(nativeKeyEvent)(JNIEnv * env, jobject thiz, jint keyCode, jboolean isPressed)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
int keyInWeb = -1;
|
||||
// key values in web, refer to http://docs.cocos.com/creator/api/en/enums/KEY.html
|
||||
switch(keyCode)
|
||||
{
|
||||
case KEYCODE_BACK:
|
||||
keyInWeb = 6;
|
||||
break;
|
||||
case KEYCODE_ENTER:
|
||||
keyInWeb = 13;
|
||||
break;
|
||||
case KEYCODE_MENU:
|
||||
keyInWeb = 18;
|
||||
break;
|
||||
case KEYCODE_DPAD_UP:
|
||||
keyInWeb = 1003;
|
||||
break;
|
||||
case KEYCODE_DPAD_DOWN:
|
||||
keyInWeb = 1004;
|
||||
break;
|
||||
case KEYCODE_DPAD_LEFT:
|
||||
keyInWeb = 1000;
|
||||
break;
|
||||
case KEYCODE_DPAD_RIGHT:
|
||||
keyInWeb = 1001;
|
||||
break;
|
||||
case KEYCODE_DPAD_CENTER:
|
||||
keyInWeb = 1005;
|
||||
break;
|
||||
default:
|
||||
keyInWeb = 0; // If the key can't be identified, this value is 0
|
||||
}
|
||||
KeyboardEvent event;
|
||||
event.key = keyInWeb;
|
||||
event.action = isPressed ? KeyboardEvent::Action::PRESS : KeyboardEvent::Action::RELEASE;
|
||||
EventDispatcher::dispatchKeyboardEvent(event);
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Cocos2dxHelper native functions implementation.
|
||||
***********************************************************/
|
||||
|
||||
JNIEXPORT void JNICALL JNI_HELPER(nativeSetApkPath)(JNIEnv* env, jobject thiz, jstring apkPath)
|
||||
{
|
||||
g_apkPath = JniHelper::jstring2string(apkPath);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_HELPER(nativeSetContext)(JNIEnv* env, jobject thiz, jobject context, jobject assetManager)
|
||||
{
|
||||
JniHelper::setClassLoaderFrom(context);
|
||||
FileUtilsAndroid::setassetmanager(AAssetManager_fromJava(env, assetManager));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_HELPER(nativeSetAudioDeviceInfo)(JNIEnv* env, jobject thiz, jboolean isSupportLowLatency, jint deviceSampleRate, jint deviceAudioBufferSizeInFrames)
|
||||
{
|
||||
g_deviceSampleRate = deviceSampleRate;
|
||||
g_deviceAudioBufferSizeInFrames = deviceAudioBufferSizeInFrames;
|
||||
LOGD("nativeSetAudioDeviceInfo: sampleRate: %d, bufferSizeInFrames: %d", g_deviceSampleRate, g_deviceAudioBufferSizeInFrames);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_HELPER(nativeSetEditTextDialogResult)(JNIEnv* env, jobject obj, jbyteArray text)
|
||||
{
|
||||
jsize size = env->GetArrayLength(text);
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
jbyte * data = (jbyte*)env->GetByteArrayElements(text, 0);
|
||||
char* buffer = (char*)malloc(size+1);
|
||||
if (buffer != nullptr)
|
||||
{
|
||||
memcpy(buffer, data, size);
|
||||
buffer[size] = '\0';
|
||||
// pass data to edittext's delegate
|
||||
if (s_editTextCallback)
|
||||
s_editTextCallback(buffer, s_ctx);
|
||||
free(buffer);
|
||||
}
|
||||
env->ReleaseByteArrayElements(text, data, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s_editTextCallback)
|
||||
s_editTextCallback("", s_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Cocos2dxAudioFocusManager native functions implementation.
|
||||
***********************************************************/
|
||||
|
||||
JNIEXPORT void JNICALL JNI_AUDIO(nativeOnAudioFocusChange)(JNIEnv* env, jobject thiz, jint focusChange)
|
||||
{
|
||||
// cocos_audioengine_focus_change(focusChange);
|
||||
}
|
||||
} // end of extern "C"
|
||||
|
||||
void restartJSVM()
|
||||
{
|
||||
g_isStarted = false;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Functions invoke from cpp to Java.
|
||||
***********************************************************/
|
||||
|
||||
std::string getApkPathJNI()
|
||||
{
|
||||
return g_apkPath;
|
||||
}
|
||||
|
||||
std::string getPackageNameJNI()
|
||||
{
|
||||
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getPackageName");
|
||||
}
|
||||
|
||||
int getObbAssetFileDescriptorJNI(const std::string& path, long* startOffset, long* size)
|
||||
{
|
||||
JniMethodInfo methodInfo;
|
||||
int fd = 0;
|
||||
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo, JCLS_HELPER, "getObbAssetFileDescriptor", "(Ljava/lang/String;)[J"))
|
||||
{
|
||||
jstring stringArg = methodInfo.env->NewStringUTF(path.c_str());
|
||||
jlongArray newArray = (jlongArray)methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID, stringArg);
|
||||
jsize theArrayLen = methodInfo.env->GetArrayLength(newArray);
|
||||
|
||||
if (3 == theArrayLen)
|
||||
{
|
||||
jboolean copy = JNI_FALSE;
|
||||
jlong *array = methodInfo.env->GetLongArrayElements(newArray, ©);
|
||||
fd = static_cast<int>(array[0]);
|
||||
*startOffset = array[1];
|
||||
*size = array[2];
|
||||
methodInfo.env->ReleaseLongArrayElements(newArray, array, 0);
|
||||
}
|
||||
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
methodInfo.env->DeleteLocalRef(stringArg);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int getDeviceSampleRateJNI()
|
||||
{
|
||||
return g_deviceSampleRate;
|
||||
}
|
||||
|
||||
int getDeviceAudioBufferSizeInFramesJNI()
|
||||
{
|
||||
return g_deviceAudioBufferSizeInFrames;
|
||||
}
|
||||
|
||||
void convertEncodingJNI(const std::string& src, int byteSize, const std::string& fromCharset, std::string& dst, const std::string& newCharset)
|
||||
{
|
||||
JniMethodInfo methodInfo;
|
||||
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo, JCLS_HELPER, "conversionEncoding", "([BLjava/lang/String;Ljava/lang/String;)[B"))
|
||||
{
|
||||
jbyteArray strArray = methodInfo.env->NewByteArray(byteSize);
|
||||
methodInfo.env->SetByteArrayRegion(strArray, 0, byteSize, reinterpret_cast<const jbyte*>(src.c_str()));
|
||||
|
||||
jstring stringArg1 = methodInfo.env->NewStringUTF(fromCharset.c_str());
|
||||
jstring stringArg2 = methodInfo.env->NewStringUTF(newCharset.c_str());
|
||||
|
||||
jbyteArray newArray = (jbyteArray)methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID, strArray, stringArg1, stringArg2);
|
||||
jsize theArrayLen = methodInfo.env->GetArrayLength(newArray);
|
||||
methodInfo.env->GetByteArrayRegion(newArray, 0, theArrayLen, (jbyte*)dst.c_str());
|
||||
|
||||
methodInfo.env->DeleteLocalRef(strArray);
|
||||
methodInfo.env->DeleteLocalRef(stringArg1);
|
||||
methodInfo.env->DeleteLocalRef(stringArg2);
|
||||
methodInfo.env->DeleteLocalRef(newArray);
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
}
|
||||
|
||||
std::string getCurrentLanguageJNI()
|
||||
{
|
||||
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getCurrentLanguage");
|
||||
}
|
||||
|
||||
std::string getCurrentLanguageCodeJNI()
|
||||
{
|
||||
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getCurrentLanguageCode");
|
||||
}
|
||||
|
||||
std::string getSystemVersionJNI()
|
||||
{
|
||||
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getSystemVersion");
|
||||
}
|
||||
|
||||
bool openURLJNI(const std::string& url)
|
||||
{
|
||||
return JniHelper::callStaticBooleanMethod(JCLS_HELPER, "openURL", url);
|
||||
}
|
||||
|
||||
void copyTextToClipboardJNI(const std::string& text)
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "copyTextToClipboard", text);
|
||||
}
|
||||
|
||||
void setPreferredFramesPerSecondJNI(int fps)
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_RENDERER, "setPreferredFramesPerSecond", fps);
|
||||
}
|
||||
|
||||
void setGameInfoDebugViewTextJNI(int index, const std::string& text)
|
||||
{
|
||||
if (!__isOpenDebugView)
|
||||
return;
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "setGameInfoDebugViewText", index, text);
|
||||
}
|
||||
|
||||
void setJSBInvocationCountJNI(int count)
|
||||
{
|
||||
if (!__isOpenDebugView)
|
||||
return;
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "setJSBInvocationCount", count);
|
||||
}
|
||||
|
||||
void openDebugViewJNI()
|
||||
{
|
||||
if (!__isOpenDebugView)
|
||||
{
|
||||
LOGD("openDebugViewJNI ...");
|
||||
__isOpenDebugView = true;
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "openDebugView");
|
||||
if (!__isGLOptModeEnabled)
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "disableBatchGLCommandsToNative");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void disableBatchGLCommandsToNativeJNI()
|
||||
{
|
||||
__isGLOptModeEnabled = false;
|
||||
if (__isOpenDebugView)
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "disableBatchGLCommandsToNative");
|
||||
}
|
||||
}
|
||||
|
||||
void exitApplication()
|
||||
{
|
||||
g_isGameFinished = true;
|
||||
}
|
||||
|
||||
|
||||
bool getApplicationExited()
|
||||
{
|
||||
return g_isGameFinished;
|
||||
}
|
||||
|
||||
int getAndroidSDKInt()
|
||||
{
|
||||
return g_SDKInt;
|
||||
}
|
||||
|
||||
|
||||
54
cocos2d-x/cocos/platform/android/jni/JniImp.h
Normal file
54
cocos2d-x/cocos/platform/android/jni/JniImp.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
typedef void (*EditTextCallback)(const std::string& text, void* ctx);
|
||||
|
||||
extern bool getApplicationExited();
|
||||
|
||||
extern void restartJSVM();
|
||||
extern void exitApplication();
|
||||
|
||||
extern std::string getApkPathJNI();
|
||||
extern std::string getPackageNameJNI();
|
||||
extern int getObbAssetFileDescriptorJNI(const std::string& path, long* startOffset, long* size);
|
||||
extern void convertEncodingJNI(const std::string& src, int byteSize, const std::string& fromCharset, std::string& dst, const std::string& newCharset);
|
||||
|
||||
extern int getDeviceSampleRateJNI();
|
||||
extern int getDeviceAudioBufferSizeInFramesJNI();
|
||||
|
||||
extern std::string getCurrentLanguageJNI();
|
||||
extern std::string getCurrentLanguageCodeJNI();
|
||||
extern std::string getSystemVersionJNI();
|
||||
extern bool openURLJNI(const std::string& url);
|
||||
extern void copyTextToClipboardJNI(const std::string& text);
|
||||
extern void setPreferredFramesPerSecondJNI(int fps);
|
||||
extern void setGameInfoDebugViewTextJNI(int index, const std::string& text);
|
||||
extern void setJSBInvocationCountJNI(int count);
|
||||
extern void openDebugViewJNI();
|
||||
extern void disableBatchGLCommandsToNativeJNI();
|
||||
extern int getAndroidSDKInt();
|
||||
7
cocos2d-x/cocos/platform/android/libcocos2dx/.gitignore
vendored
Normal file
7
cocos2d-x/cocos/platform/android/libcocos2dx/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
@@ -0,0 +1,4 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.cocos2dx.lib">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
</manifest>
|
||||
34
cocos2d-x/cocos/platform/android/libcocos2dx/build.gradle
Normal file
34
cocos2d-x/cocos/platform/android/libcocos2dx/build.gradle
Normal file
@@ -0,0 +1,34 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion PROP_COMPILE_SDK_VERSION.toInteger()
|
||||
buildToolsVersion PROP_BUILD_TOOLS_VERSION
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion PROP_MIN_SDK_VERSION
|
||||
targetSdkVersion PROP_TARGET_SDK_VERSION
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
|
||||
sourceSets.main {
|
||||
aidl.srcDir "../java/src"
|
||||
java.srcDir "../java/src"
|
||||
manifest.srcFile "AndroidManifest.xml"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: '../java/libs')
|
||||
}
|
||||
17
cocos2d-x/cocos/platform/android/libcocos2dx/proguard-rules.pro
vendored
Normal file
17
cocos2d-x/cocos/platform/android/libcocos2dx/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in E:\developSoftware\Android\SDK/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!--EditBox Confirm Button Name-->
|
||||
<string name="done" translatable="false">完成</string>
|
||||
<string name="next" translatable="false">下一个</string>
|
||||
<string name="search" translatable="false">搜索</string>
|
||||
<string name="go" translatable="false">前往</string>
|
||||
<string name="send" translatable="false">发送</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!--EditBox Confirm Button Title-->
|
||||
<string name="done" translatable="false">Done</string>
|
||||
<string name="next" translatable="false">Next</string>
|
||||
<string name="search" translatable="false">Search</string>
|
||||
<string name="go" translatable="false">Go</string>
|
||||
<string name="send" translatable="false">Send</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,850 @@
|
||||
#include "platform/CCCanvasRenderingContext2D.h"
|
||||
#include "base/ccTypes.h"
|
||||
#include "base/csscolorparser.hpp"
|
||||
#include "base/ccUTF8.h"
|
||||
|
||||
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "cocos/scripting/js-bindings/manual/jsb_platform.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#else
|
||||
#import <CoreText/CoreText.h>
|
||||
|
||||
#define NSBezierPath UIBezierPath
|
||||
#define NSFont UIFont
|
||||
#define NSColor UIColor
|
||||
#define NSSize CGSize
|
||||
#define NSZeroSize CGSizeZero
|
||||
#define NSPoint CGPoint
|
||||
#define NSMakePoint CGPointMake
|
||||
|
||||
#endif
|
||||
|
||||
#include <regex>
|
||||
enum class CanvasTextAlign {
|
||||
LEFT,
|
||||
CENTER,
|
||||
RIGHT
|
||||
};
|
||||
|
||||
enum class CanvasTextBaseline {
|
||||
TOP,
|
||||
MIDDLE,
|
||||
BOTTOM
|
||||
};
|
||||
|
||||
@interface CanvasRenderingContext2DImpl : NSObject {
|
||||
NSFont* _font;
|
||||
NSMutableDictionary* _tokenAttributesDict;
|
||||
NSString* _fontName;
|
||||
CGFloat _fontSize;
|
||||
CGFloat _width;
|
||||
CGFloat _height;
|
||||
CGContextRef _context;
|
||||
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
NSGraphicsContext* _currentGraphicsContext;
|
||||
NSGraphicsContext* _oldGraphicsContext;
|
||||
#else
|
||||
CGContextRef _oldContext;
|
||||
#endif
|
||||
|
||||
CGColorSpaceRef _colorSpace;
|
||||
cocos2d::Data _imageData;
|
||||
NSBezierPath* _path;
|
||||
|
||||
CanvasTextAlign _textAlign;
|
||||
CanvasTextBaseline _textBaseLine;
|
||||
cocos2d::Color4F _fillStyle;
|
||||
cocos2d::Color4F _strokeStyle;
|
||||
float _lineWidth;
|
||||
bool _bold;
|
||||
}
|
||||
|
||||
@property (nonatomic, strong) NSFont* font;
|
||||
@property (nonatomic, strong) NSMutableDictionary* tokenAttributesDict;
|
||||
@property (nonatomic, strong) NSString* fontName;
|
||||
@property (nonatomic, assign) CanvasTextAlign textAlign;
|
||||
@property (nonatomic, assign) CanvasTextBaseline textBaseLine;
|
||||
@property (nonatomic, assign) float lineWidth;
|
||||
|
||||
@end
|
||||
|
||||
@implementation CanvasRenderingContext2DImpl
|
||||
|
||||
@synthesize font = _font;
|
||||
@synthesize tokenAttributesDict = _tokenAttributesDict;
|
||||
@synthesize fontName = _fontName;
|
||||
@synthesize textAlign = _textAlign;
|
||||
@synthesize textBaseLine = _textBaseLine;
|
||||
@synthesize lineWidth = _lineWidth;
|
||||
|
||||
-(id) init {
|
||||
if (self = [super init]) {
|
||||
_lineWidth = 0;
|
||||
_textAlign = CanvasTextAlign::LEFT;
|
||||
_textBaseLine = CanvasTextBaseline::BOTTOM;
|
||||
_width = _height = 0;
|
||||
_context = nil;
|
||||
_colorSpace = nil;
|
||||
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
_currentGraphicsContext = nil;
|
||||
_oldGraphicsContext = nil;
|
||||
#endif
|
||||
_path = [NSBezierPath bezierPath];
|
||||
[_path retain];
|
||||
[self updateFontWithName:@"Arial" fontSize:30 bold:false];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) dealloc {
|
||||
self.font = nil;
|
||||
self.tokenAttributesDict = nil;
|
||||
self.fontName = nil;
|
||||
CGColorSpaceRelease(_colorSpace);
|
||||
// release the context
|
||||
CGContextRelease(_context);
|
||||
[_path release];
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
[_currentGraphicsContext release];
|
||||
#endif
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
|
||||
-(NSFont*) _createSystemFont {
|
||||
NSFontTraitMask mask = NSUnitalicFontMask;
|
||||
if (_bold) {
|
||||
mask |= NSBoldFontMask;
|
||||
}
|
||||
else {
|
||||
mask |= NSUnboldFontMask;
|
||||
}
|
||||
|
||||
NSFont* font = [[NSFontManager sharedFontManager]
|
||||
fontWithFamily:_fontName
|
||||
traits:mask
|
||||
weight:0
|
||||
size:_fontSize];
|
||||
|
||||
if (font == nil) {
|
||||
const auto& familyMap = getFontFamilyNameMap();
|
||||
auto iter = familyMap.find([_fontName UTF8String]);
|
||||
if (iter != familyMap.end()) {
|
||||
font = [[NSFontManager sharedFontManager]
|
||||
fontWithFamily: [NSString stringWithUTF8String:iter->second.c_str()]
|
||||
traits: mask
|
||||
weight: 0
|
||||
size: _fontSize];
|
||||
}
|
||||
}
|
||||
|
||||
if (font == nil) {
|
||||
font = [[NSFontManager sharedFontManager]
|
||||
fontWithFamily: @"Arial"
|
||||
traits: mask
|
||||
weight: 0
|
||||
size: _fontSize];
|
||||
}
|
||||
return font;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
-(UIFont*) _createSystemFont {
|
||||
UIFont* font = nil;
|
||||
|
||||
if (_bold) {
|
||||
font = [UIFont fontWithName:[_fontName stringByAppendingString:@"-Bold"] size:_fontSize];
|
||||
}
|
||||
else {
|
||||
font = [UIFont fontWithName:_fontName size:_fontSize];
|
||||
}
|
||||
|
||||
if (font == nil) {
|
||||
const auto& familyMap = getFontFamilyNameMap();
|
||||
auto iter = familyMap.find([_fontName UTF8String]);
|
||||
if (iter != familyMap.end()) {
|
||||
font = [UIFont fontWithName:[NSString stringWithUTF8String:iter->second.c_str()] size:_fontSize];
|
||||
}
|
||||
}
|
||||
|
||||
if (font == nil) {
|
||||
if (_bold) {
|
||||
font = [UIFont boldSystemFontOfSize:_fontSize];
|
||||
} else {
|
||||
font = [UIFont systemFontOfSize:_fontSize];
|
||||
}
|
||||
}
|
||||
return font;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
-(void) updateFontWithName: (NSString*)fontName fontSize: (CGFloat)fontSize bold: (bool)bold{
|
||||
_fontSize = fontSize;
|
||||
_bold = bold;
|
||||
|
||||
self.fontName = fontName;
|
||||
self.font = [self _createSystemFont];
|
||||
|
||||
NSMutableParagraphStyle* paragraphStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
|
||||
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
[paragraphStyle setAlignment:NSTextAlignmentCenter];
|
||||
|
||||
// color
|
||||
NSColor* foregroundColor = [NSColor colorWithRed:1.0f
|
||||
green:1.0f
|
||||
blue:1.0f
|
||||
alpha:1.0f];
|
||||
|
||||
// attribute
|
||||
self.tokenAttributesDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||
foregroundColor, NSForegroundColorAttributeName,
|
||||
_font, NSFontAttributeName,
|
||||
paragraphStyle, NSParagraphStyleAttributeName, nil];
|
||||
}
|
||||
|
||||
-(void) recreateBufferWithWidth:(NSInteger) width height:(NSInteger) height {
|
||||
_width = width = width > 0 ? width : 1;
|
||||
_height = height = height > 0 ? height : 1;
|
||||
NSUInteger textureSize = width * height * 4;
|
||||
unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char) * textureSize);
|
||||
memset(data, 0, textureSize);
|
||||
_imageData.fastSet(data, textureSize);
|
||||
|
||||
if (_context != nil)
|
||||
{
|
||||
CGContextRelease(_context);
|
||||
_context = nil;
|
||||
}
|
||||
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
if (_currentGraphicsContext != nil)
|
||||
{
|
||||
[_currentGraphicsContext release];
|
||||
_currentGraphicsContext = nil;
|
||||
}
|
||||
#endif
|
||||
|
||||
// draw text
|
||||
_colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
_context = CGBitmapContextCreate(data,
|
||||
width,
|
||||
height,
|
||||
8,
|
||||
width * 4,
|
||||
_colorSpace,
|
||||
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
|
||||
if (nil == _context)
|
||||
{
|
||||
CGColorSpaceRelease(_colorSpace); //REFINE: HOWTO RELEASE?
|
||||
_colorSpace = nil;
|
||||
}
|
||||
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
_currentGraphicsContext = [NSGraphicsContext graphicsContextWithCGContext:_context flipped: NO];
|
||||
[_currentGraphicsContext retain];
|
||||
#else
|
||||
// move Y rendering to the top of the image
|
||||
CGContextTranslateCTM(_context, 0.0f, _height);
|
||||
|
||||
//NOTE: NSString draws in UIKit referential i.e. renders upside-down compared to CGBitmapContext referential
|
||||
CGContextScaleCTM(_context, 1.0f, -1.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
-(NSSize) measureText:(NSString*) text {
|
||||
|
||||
NSAttributedString* stringWithAttributes = [[[NSAttributedString alloc] initWithString:text
|
||||
attributes:_tokenAttributesDict] autorelease];
|
||||
|
||||
NSSize textRect = NSZeroSize;
|
||||
textRect.width = CGFLOAT_MAX;
|
||||
textRect.height = CGFLOAT_MAX;
|
||||
|
||||
NSSize dim = [stringWithAttributes boundingRectWithSize:textRect options:(NSStringDrawingOptions)(NSStringDrawingUsesLineFragmentOrigin) context:nil].size;
|
||||
|
||||
return dim;
|
||||
}
|
||||
|
||||
-(NSPoint) convertDrawPoint:(NSPoint) point text:(NSString*) text {
|
||||
// The parameter 'point' is located at left-bottom position.
|
||||
// Need to adjust 'point' according 'text align' & 'text base line'.
|
||||
NSSize textSize = [self measureText:text];
|
||||
|
||||
if (_textAlign == CanvasTextAlign::CENTER)
|
||||
{
|
||||
point.x -= textSize.width / 2.0f;
|
||||
}
|
||||
else if (_textAlign == CanvasTextAlign::RIGHT)
|
||||
{
|
||||
point.x -= textSize.width;
|
||||
}
|
||||
|
||||
if (_textBaseLine == CanvasTextBaseline::TOP)
|
||||
{
|
||||
point.y += _fontSize;
|
||||
}
|
||||
else if (_textBaseLine == CanvasTextBaseline::MIDDLE)
|
||||
{
|
||||
point.y += _fontSize / 2.0f;
|
||||
}
|
||||
|
||||
// Since the web platform cannot get the baseline of the font, an additive offset is performed for all platforms.
|
||||
// That's why we should add baseline back again on other platforms
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
point.y -= _font.descender;
|
||||
|
||||
// The origin on macOS is bottom-left by default, so we need to convert y from top-left origin to bottom-left origin.
|
||||
point.y = _height - point.y;
|
||||
#else
|
||||
point.y -= _font.ascender;
|
||||
#endif
|
||||
return point;
|
||||
}
|
||||
|
||||
-(void) fillText:(NSString*) text x:(CGFloat) x y:(CGFloat) y maxWidth:(CGFloat) maxWidth {
|
||||
if (text.length == 0)
|
||||
return;
|
||||
|
||||
NSPoint drawPoint = [self convertDrawPoint:NSMakePoint(x, y) text:text];
|
||||
|
||||
NSMutableParagraphStyle* paragraphStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
|
||||
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
|
||||
[_tokenAttributesDict removeObjectForKey:NSStrokeColorAttributeName];
|
||||
|
||||
[_tokenAttributesDict setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
|
||||
[_tokenAttributesDict setObject:[NSColor colorWithRed:_fillStyle.r green:_fillStyle.g blue:_fillStyle.b alpha:_fillStyle.a]
|
||||
forKey:NSForegroundColorAttributeName];
|
||||
|
||||
[self saveContext];
|
||||
|
||||
// text color
|
||||
CGContextSetRGBFillColor(_context, _fillStyle.r, _fillStyle.g, _fillStyle.b, _fillStyle.a);
|
||||
CGContextSetShouldSubpixelQuantizeFonts(_context, false);
|
||||
CGContextBeginTransparencyLayerWithRect(_context, CGRectMake(0, 0, _width, _height), nullptr);
|
||||
CGContextSetTextDrawingMode(_context, kCGTextFill);
|
||||
|
||||
|
||||
|
||||
NSAttributedString *stringWithAttributes =[[[NSAttributedString alloc] initWithString:text
|
||||
attributes:_tokenAttributesDict] autorelease];
|
||||
|
||||
[stringWithAttributes drawAtPoint:drawPoint];
|
||||
|
||||
|
||||
CGContextEndTransparencyLayer(_context);
|
||||
|
||||
[self restoreContext];
|
||||
}
|
||||
|
||||
-(void) strokeText:(NSString*) text x:(CGFloat) x y:(CGFloat) y maxWidth:(CGFloat) maxWidth {
|
||||
if (text.length == 0)
|
||||
return;
|
||||
|
||||
NSPoint drawPoint = [self convertDrawPoint:NSMakePoint(x, y) text:text];
|
||||
|
||||
NSMutableParagraphStyle* paragraphStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
|
||||
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
|
||||
[_tokenAttributesDict removeObjectForKey:NSForegroundColorAttributeName];
|
||||
|
||||
[_tokenAttributesDict setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
|
||||
[_tokenAttributesDict setObject:[NSColor colorWithRed:_strokeStyle.r
|
||||
green:_strokeStyle.g
|
||||
blue:_strokeStyle.b
|
||||
alpha:_strokeStyle.a] forKey:NSStrokeColorAttributeName];
|
||||
|
||||
[self saveContext];
|
||||
|
||||
// text color
|
||||
CGContextSetRGBStrokeColor(_context, _strokeStyle.r, _strokeStyle.g, _strokeStyle.b, _strokeStyle.a);
|
||||
CGContextSetRGBFillColor(_context, _fillStyle.r, _fillStyle.g, _fillStyle.b, _fillStyle.a);
|
||||
CGContextSetLineWidth(_context, _lineWidth);
|
||||
CGContextSetLineJoin(_context, kCGLineJoinRound);
|
||||
CGContextSetShouldSubpixelQuantizeFonts(_context, false);
|
||||
CGContextBeginTransparencyLayerWithRect(_context, CGRectMake(0, 0, _width, _height), nullptr);
|
||||
|
||||
CGContextSetTextDrawingMode(_context, kCGTextStroke);
|
||||
|
||||
NSAttributedString *stringWithAttributes =[[[NSAttributedString alloc] initWithString:text
|
||||
attributes:_tokenAttributesDict] autorelease];
|
||||
|
||||
[stringWithAttributes drawAtPoint:drawPoint];
|
||||
|
||||
CGContextEndTransparencyLayer(_context);
|
||||
|
||||
[self restoreContext];
|
||||
}
|
||||
|
||||
-(void) setFillStyleWithRed:(CGFloat) r green:(CGFloat) g blue:(CGFloat) b alpha:(CGFloat) a {
|
||||
_fillStyle.r = r;
|
||||
_fillStyle.g = g;
|
||||
_fillStyle.b = b;
|
||||
_fillStyle.a = a;
|
||||
}
|
||||
|
||||
-(void) setStrokeStyleWithRed:(CGFloat) r green:(CGFloat) g blue:(CGFloat) b alpha:(CGFloat) a {
|
||||
_strokeStyle.r = r;
|
||||
_strokeStyle.g = g;
|
||||
_strokeStyle.b = b;
|
||||
_strokeStyle.a = a;
|
||||
}
|
||||
|
||||
-(const cocos2d::Data&) getDataRef {
|
||||
return _imageData;
|
||||
}
|
||||
|
||||
-(void) clearRect:(CGRect) rect {
|
||||
if (_imageData.isNull())
|
||||
return;
|
||||
|
||||
rect.origin.x = floor(rect.origin.x);
|
||||
rect.origin.y = floor(rect.origin.y);
|
||||
rect.size.width = floor(rect.size.width);
|
||||
rect.size.height = floor(rect.size.height);
|
||||
|
||||
if (rect.origin.x < 0) rect.origin.x = 0;
|
||||
if (rect.origin.y < 0) rect.origin.y = 0;
|
||||
|
||||
if (rect.size.width < 1 || rect.size.height < 1)
|
||||
return;
|
||||
//REFINE:
|
||||
// assert(rect.origin.x == 0 && rect.origin.y == 0);
|
||||
memset((void*)_imageData.getBytes(), 0x00, _imageData.getSize());
|
||||
}
|
||||
|
||||
-(void) fillRect:(CGRect) rect {
|
||||
[self saveContext];
|
||||
|
||||
NSColor* color = [NSColor colorWithRed:_fillStyle.r green:_fillStyle.g blue:_fillStyle.b alpha:_fillStyle.a];
|
||||
[color setFill];
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
CGRect tmpRect = CGRectMake(rect.origin.x, _height - rect.origin.y - rect.size.height, rect.size.width, rect.size.height);
|
||||
[NSBezierPath fillRect:tmpRect];
|
||||
#else
|
||||
NSBezierPath* path = [NSBezierPath bezierPathWithRect:rect];
|
||||
[path fill];
|
||||
#endif
|
||||
[self restoreContext];
|
||||
}
|
||||
|
||||
-(void) saveContext {
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
// save the old graphics context
|
||||
_oldGraphicsContext = [NSGraphicsContext currentContext];
|
||||
// store the current context
|
||||
[NSGraphicsContext setCurrentContext:_currentGraphicsContext];
|
||||
// push graphics state to stack
|
||||
[NSGraphicsContext saveGraphicsState];
|
||||
[[NSGraphicsContext currentContext] setShouldAntialias:YES];
|
||||
#else
|
||||
// save the old graphics context
|
||||
_oldContext = UIGraphicsGetCurrentContext();
|
||||
// store the current context
|
||||
UIGraphicsPushContext(_context);
|
||||
CGContextSaveGState(_context);
|
||||
#endif
|
||||
}
|
||||
|
||||
-(void) restoreContext {
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
// pop the context
|
||||
[NSGraphicsContext restoreGraphicsState];
|
||||
// reset the old graphics context
|
||||
[NSGraphicsContext setCurrentContext:_oldGraphicsContext];
|
||||
_oldGraphicsContext = nil;
|
||||
#else
|
||||
// pop the context
|
||||
CGContextRestoreGState(_context);
|
||||
// reset the old graphics context
|
||||
UIGraphicsPopContext();
|
||||
_oldContext = nil;
|
||||
#endif
|
||||
}
|
||||
|
||||
-(void) beginPath {
|
||||
|
||||
}
|
||||
|
||||
-(void) stroke {
|
||||
NSColor* color = [NSColor colorWithRed:_strokeStyle.r green:_strokeStyle.g blue:_strokeStyle.b alpha:_strokeStyle.a];
|
||||
[color setStroke];
|
||||
[_path setLineWidth: _lineWidth];
|
||||
[_path stroke];
|
||||
}
|
||||
|
||||
-(void) moveToX: (float) x y:(float) y {
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
[_path moveToPoint: NSMakePoint(x, _height - y)];
|
||||
#else
|
||||
[_path moveToPoint: NSMakePoint(x, y)];
|
||||
#endif
|
||||
}
|
||||
|
||||
-(void) lineToX: (float) x y:(float) y {
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
[_path lineToPoint: NSMakePoint(x, _height - y)];
|
||||
#else
|
||||
[_path addLineToPoint: NSMakePoint(x, y)];
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
CanvasGradient::CanvasGradient()
|
||||
{
|
||||
SE_LOGD("CanvasGradient constructor: %p\n", this);
|
||||
}
|
||||
|
||||
CanvasGradient::~CanvasGradient()
|
||||
{
|
||||
SE_LOGD("CanvasGradient destructor: %p\n", this);
|
||||
}
|
||||
|
||||
void CanvasGradient::addColorStop(float offset, const std::string& color)
|
||||
{
|
||||
SE_LOGD("CanvasGradient::addColorStop: %p\n", this);
|
||||
}
|
||||
|
||||
// CanvasRenderingContext2D
|
||||
|
||||
namespace
|
||||
{
|
||||
#define CLAMP(V, HI) std::min( (V), (HI) )
|
||||
void unMultiplyAlpha(unsigned char* ptr, ssize_t size)
|
||||
{
|
||||
float alpha;
|
||||
for (int i = 0; i < size; i += 4)
|
||||
{
|
||||
alpha = (float)ptr[i + 3];
|
||||
if (alpha > 0)
|
||||
{
|
||||
ptr[i] = CLAMP((int)((float)ptr[i] / alpha * 255), 255);
|
||||
ptr[i+1] = CLAMP((int)((float)ptr[i+1] / alpha * 255), 255);
|
||||
ptr[i+2] = CLAMP((int)((float)ptr[i+2] / alpha * 255), 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define SEND_DATA_TO_JS(CB, IMPL, PREMULTIPLY) \
|
||||
if (CB) \
|
||||
{ \
|
||||
Data data([IMPL getDataRef]); \
|
||||
if (!PREMULTIPLY) \
|
||||
{ \
|
||||
unMultiplyAlpha(data.getBytes(), data.getSize() ); \
|
||||
} \
|
||||
CB(data); \
|
||||
}
|
||||
|
||||
CanvasRenderingContext2D::CanvasRenderingContext2D(float width, float height)
|
||||
: __width(width)
|
||||
, __height(height)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D constructor: %p, width: %f, height: %f\n", this, width, height);
|
||||
_impl = [[CanvasRenderingContext2DImpl alloc] init];
|
||||
[_impl recreateBufferWithWidth:width height:height];
|
||||
}
|
||||
|
||||
CanvasRenderingContext2D::~CanvasRenderingContext2D()
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D destructor: %p\n", this);
|
||||
[_impl release];
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::recreateBufferIfNeeded()
|
||||
{
|
||||
if (_isBufferSizeDirty)
|
||||
{
|
||||
_isBufferSizeDirty = false;
|
||||
// SE_LOGD("CanvasRenderingContext2D::recreateBufferIfNeeded %p, w: %f, h:%f\n", this, __width, __height);
|
||||
[_impl recreateBufferWithWidth: __width height:__height];
|
||||
SEND_DATA_TO_JS(_canvasBufferUpdatedCB, _impl, _premultiply);
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height)
|
||||
{
|
||||
// SE_LOGD("CanvasGradient::clearRect: %p, %f, %f, %f, %f\n", this, x, y, width, height);
|
||||
recreateBufferIfNeeded();
|
||||
[_impl clearRect:CGRectMake(x, y, width, height)];
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::fillRect(float x, float y, float width, float height)
|
||||
{
|
||||
recreateBufferIfNeeded();
|
||||
[_impl fillRect:CGRectMake(x, y, width, height)];
|
||||
SEND_DATA_TO_JS(_canvasBufferUpdatedCB, _impl, _premultiply);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::fillText(const std::string& text, float x, float y, float maxWidth)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D(%p)::fillText: %s, %f, %f, %f\n", this, text.c_str(), x, y, maxWidth);
|
||||
if (text.empty())
|
||||
return;
|
||||
|
||||
recreateBufferIfNeeded();
|
||||
|
||||
auto textUtf8 = [NSString stringWithUTF8String:text.c_str()];
|
||||
if(textUtf8 == nullptr) {
|
||||
SE_LOGE("CanvasRenderingContext2D::fillText failed to convert text to UTF8\n text:\"%s\"", text.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
[_impl fillText:textUtf8 x:x y:y maxWidth:maxWidth];
|
||||
SEND_DATA_TO_JS(_canvasBufferUpdatedCB, _impl, _premultiply);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::strokeText(const std::string& text, float x, float y, float maxWidth)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D(%p)::strokeText: %s, %f, %f, %f\n", this, text.c_str(), x, y, maxWidth);
|
||||
if (text.empty())
|
||||
return;
|
||||
recreateBufferIfNeeded();
|
||||
|
||||
auto textUtf8 = [NSString stringWithUTF8String:text.c_str()];
|
||||
if(textUtf8 == nullptr) {
|
||||
SE_LOGE("CanvasRenderingContext2D::strokeText failed to convert text to UTF8\n text:\"%s\"", text.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
[_impl strokeText:textUtf8 x:x y:y maxWidth:maxWidth];
|
||||
SEND_DATA_TO_JS(_canvasBufferUpdatedCB, _impl, _premultiply);
|
||||
}
|
||||
|
||||
cocos2d::Size CanvasRenderingContext2D::measureText(const std::string& text)
|
||||
{
|
||||
NSString *str =[NSString stringWithUTF8String:text.c_str()];
|
||||
if(str == nil) {
|
||||
std::string textNew;
|
||||
cocos2d::StringUtils::UTF8LooseFix(text, textNew);
|
||||
str = [NSString stringWithUTF8String:textNew.c_str()];
|
||||
}
|
||||
CGSize size = [_impl measureText: str];
|
||||
return cocos2d::Size(size.width, size.height);
|
||||
}
|
||||
|
||||
CanvasGradient* CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::save()
|
||||
{
|
||||
[_impl saveContext];
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::beginPath()
|
||||
{
|
||||
[_impl beginPath];
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::closePath()
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::moveTo(float x, float y)
|
||||
{
|
||||
[_impl moveToX:x y:y];
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::lineTo(float x, float y)
|
||||
{
|
||||
[_impl lineToX:x y:y];
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::stroke()
|
||||
{
|
||||
[_impl stroke];
|
||||
SEND_DATA_TO_JS(_canvasBufferUpdatedCB, _impl, _premultiply);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::fill()
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::rect(float x, float y, float w, float h)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::restore()
|
||||
{
|
||||
[_impl restoreContext];
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::setCanvasBufferUpdatedCallback(const CanvasBufferUpdatedCallback& cb)
|
||||
{
|
||||
_canvasBufferUpdatedCB = cb;
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::setPremultiply(bool multiply)
|
||||
{
|
||||
_premultiply = multiply;
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set__width(float width)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D::set__width: %f\n", width);
|
||||
__width = width;
|
||||
_isBufferSizeDirty = true;
|
||||
recreateBufferIfNeeded();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set__height(float height)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D::set__height: %f\n", height);
|
||||
__height = height;
|
||||
_isBufferSizeDirty = true;
|
||||
recreateBufferIfNeeded();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_lineWidth(float lineWidth)
|
||||
{
|
||||
_lineWidth = lineWidth;
|
||||
_impl.lineWidth = _lineWidth;
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_lineCap(const std::string& lineCap)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_lineJoin(const std::string& lineJoin)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_font(const std::string& font)
|
||||
{
|
||||
if (_font != font)
|
||||
{
|
||||
_font = font;
|
||||
|
||||
std::string boldStr;
|
||||
std::string fontName = "Arial";
|
||||
std::string fontSizeStr = "30";
|
||||
|
||||
// support get font name from `60px American` or `60px "American abc-abc_abc"`
|
||||
std::regex re("(bold)?\\s*((\\d+)([\\.]\\d+)?)px\\s+([\\w-]+|\"[\\w -]+\"$)");
|
||||
std::match_results<std::string::const_iterator> results;
|
||||
if (std::regex_search(_font.cbegin(), _font.cend(), results, re))
|
||||
{
|
||||
boldStr = results[1].str();
|
||||
fontSizeStr = results[2].str();
|
||||
fontName = results[5].str();
|
||||
}
|
||||
|
||||
CGFloat fontSize = atof(fontSizeStr.c_str());
|
||||
[_impl updateFontWithName:[NSString stringWithUTF8String:fontName.c_str()] fontSize:fontSize bold:!boldStr.empty()];
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_textAlign(const std::string& textAlign)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D::set_textAlign: %s\n", textAlign.c_str());
|
||||
if (textAlign == "left")
|
||||
{
|
||||
_impl.textAlign = CanvasTextAlign::LEFT;
|
||||
}
|
||||
else if (textAlign == "center" || textAlign == "middle")
|
||||
{
|
||||
_impl.textAlign = CanvasTextAlign::CENTER;
|
||||
}
|
||||
else if (textAlign == "right")
|
||||
{
|
||||
_impl.textAlign = CanvasTextAlign::RIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_textBaseline(const std::string& textBaseline)
|
||||
{
|
||||
// SE_LOGD("CanvasRenderingContext2D::set_textBaseline: %s\n", textBaseline.c_str());
|
||||
if (textBaseline == "top")
|
||||
{
|
||||
_impl.textBaseLine = CanvasTextBaseline::TOP;
|
||||
}
|
||||
else if (textBaseline == "middle")
|
||||
{
|
||||
_impl.textBaseLine = CanvasTextBaseline::MIDDLE;
|
||||
}
|
||||
else if (textBaseline == "bottom" || textBaseline == "alphabetic") //REFINE:, how to deal with alphabetic, currently we handle it as bottom mode.
|
||||
{
|
||||
_impl.textBaseLine = CanvasTextBaseline::BOTTOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_fillStyle(const std::string& fillStyle)
|
||||
{
|
||||
CSSColorParser::Color color = CSSColorParser::parse(fillStyle);
|
||||
[_impl setFillStyleWithRed:color.r/255.0f green:color.g/255.0f blue:color.b/255.0f alpha:color.a];
|
||||
// SE_LOGD("CanvasRenderingContext2D::set_fillStyle: %s, (%d, %d, %d, %f)\n", fillStyle.c_str(), color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_strokeStyle(const std::string& strokeStyle)
|
||||
{
|
||||
CSSColorParser::Color color = CSSColorParser::parse(strokeStyle);
|
||||
[_impl setStrokeStyleWithRed:color.r/255.0f green:color.g/255.0f blue:color.b/255.0f alpha:color.a];
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_globalCompositeOperation(const std::string& globalCompositeOperation)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::_fillImageData(const Data& imageData, float imageWidth, float imageHeight, float offsetX, float offsetY)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
// transform
|
||||
|
||||
void CanvasRenderingContext2D::translate(float x, float y)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::scale(float x, float y)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::rotate(float angle)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::transform(float a, float b, float c, float d, float e, float f)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::setTransform(float a, float b, float c, float d, float e, float f)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
32
cocos2d-x/cocos/platform/apple/CCDevice-apple.h
Normal file
32
cocos2d-x/cocos/platform/apple/CCDevice-apple.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CCDevice_apple_hpp
|
||||
#define CCDevice_apple_hpp
|
||||
|
||||
#include "platform/CCDevice.h"
|
||||
|
||||
#endif /* CCDevice_apple_hpp */
|
||||
38
cocos2d-x/cocos/platform/apple/CCDevice-apple.mm
Normal file
38
cocos2d-x/cocos/platform/apple/CCDevice-apple.mm
Normal file
@@ -0,0 +1,38 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "platform/apple/CCDevice-apple.h"
|
||||
#include "platform/CCApplication.h"
|
||||
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
int Device::getDevicePixelRatio()
|
||||
{
|
||||
return Application::getInstance()->getScreenScale();
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
80
cocos2d-x/cocos/platform/apple/CCFileUtils-apple.h
Normal file
80
cocos2d-x/cocos/platform/apple/CCFileUtils-apple.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2011 Zynga Inc.
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#ifndef __CC_FILEUTILS_APPLE_H__
|
||||
#define __CC_FILEUTILS_APPLE_H__
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include "base/ccMacros.h"
|
||||
#include "base/ccTypes.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
/**
|
||||
* @addtogroup platform
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! @brief Helper class to handle file operations
|
||||
class CC_DLL FileUtilsApple : public FileUtils
|
||||
{
|
||||
public:
|
||||
FileUtilsApple();
|
||||
virtual ~FileUtilsApple();
|
||||
/* override functions */
|
||||
virtual std::string getWritablePath() const override;
|
||||
virtual std::string getFullPathForDirectoryAndFilename(const std::string& directory, const std::string& filename) const override;
|
||||
|
||||
virtual ValueMap getValueMapFromFile(const std::string& filename) override;
|
||||
virtual ValueMap getValueMapFromData(const char* filedata, int filesize)override;
|
||||
virtual bool writeToFile(const ValueMap& dict, const std::string& fullPath) override;
|
||||
|
||||
virtual ValueVector getValueVectorFromFile(const std::string& filename) override;
|
||||
#if CC_FILEUTILS_APPLE_ENABLE_OBJC
|
||||
void setBundle(NSBundle* bundle);
|
||||
#endif
|
||||
|
||||
virtual bool createDirectory(const std::string& path) override;
|
||||
private:
|
||||
virtual bool isFileExistInternal(const std::string& filePath) const override;
|
||||
virtual bool removeDirectory(const std::string& dirPath) override;
|
||||
virtual void valueMapCompact(ValueMap& valueMap) override;
|
||||
virtual void valueVectorCompact(ValueVector& valueVector) override;
|
||||
|
||||
struct IMPL;
|
||||
std::unique_ptr<IMPL> pimpl_;
|
||||
};
|
||||
|
||||
// end of platform group
|
||||
/// @}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // __CC_FILEUTILS_APPLE_H__
|
||||
503
cocos2d-x/cocos/platform/apple/CCFileUtils-apple.mm
Normal file
503
cocos2d-x/cocos/platform/apple/CCFileUtils-apple.mm
Normal file
@@ -0,0 +1,503 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2011 Zynga Inc.
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include "platform/apple/CCFileUtils-apple.h"
|
||||
|
||||
#include <ftw.h>
|
||||
|
||||
#include <string>
|
||||
#include <stack>
|
||||
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include "platform/CCSAXParser.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
struct FileUtilsApple::IMPL {
|
||||
IMPL(NSBundle* bundle):bundle_([NSBundle mainBundle]) {}
|
||||
void setBundle(NSBundle* bundle) {
|
||||
bundle_ = bundle;
|
||||
}
|
||||
NSBundle* getBundle() const {
|
||||
return bundle_;
|
||||
}
|
||||
private:
|
||||
NSBundle* bundle_;
|
||||
};
|
||||
|
||||
static id convertCCValueToNSObject(const cocos2d::Value &value);
|
||||
static cocos2d::Value convertNSObjectToCCValue(id object);
|
||||
|
||||
static void addNSObjectToCCMap(id nsKey, id nsValue, ValueMap& dict);
|
||||
static void addCCValueToNSDictionary(const std::string& key, const Value& value, NSMutableDictionary *dict);
|
||||
static void addNSObjectToCCVector(id item, ValueVector& array);
|
||||
static void addCCValueToNSArray(const Value& value, NSMutableArray *array);
|
||||
|
||||
static id convertCCValueToNSObject(const cocos2d::Value &value)
|
||||
{
|
||||
switch (value.getType())
|
||||
{
|
||||
case Value::Type::NONE:
|
||||
return [NSNull null];
|
||||
|
||||
case Value::Type::STRING:
|
||||
return [NSString stringWithCString:value.asString().c_str() encoding:NSUTF8StringEncoding];
|
||||
|
||||
case Value::Type::BYTE:
|
||||
return [NSNumber numberWithInt:value.asByte()];
|
||||
|
||||
case Value::Type::INTEGER:
|
||||
return [NSNumber numberWithInt:value.asInt()];
|
||||
|
||||
case Value::Type::UNSIGNED:
|
||||
return [NSNumber numberWithUnsignedInt:value.asUnsignedInt()];
|
||||
|
||||
case Value::Type::FLOAT:
|
||||
return [NSNumber numberWithFloat:value.asFloat()];
|
||||
|
||||
case Value::Type::DOUBLE:
|
||||
return [NSNumber numberWithDouble:value.asDouble()];
|
||||
|
||||
case Value::Type::BOOLEAN:
|
||||
return [NSNumber numberWithBool:value.asBool()];
|
||||
|
||||
case Value::Type::VECTOR: {
|
||||
NSMutableArray *array = [NSMutableArray array];
|
||||
const ValueVector &vector = value.asValueVector();
|
||||
for (const auto &e : vector) {
|
||||
addCCValueToNSArray(e, array);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
case Value::Type::MAP: {
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
||||
const ValueMap &map = value.asValueMap();
|
||||
for (auto iter = map.begin(); iter != map.end(); ++iter) {
|
||||
addCCValueToNSDictionary(iter->first, iter->second, dictionary);
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
case Value::Type::INT_KEY_MAP:
|
||||
break;
|
||||
}
|
||||
|
||||
return [NSNull null];
|
||||
}
|
||||
|
||||
static cocos2d::Value convertNSObjectToCCValue(id item)
|
||||
{
|
||||
// add string value into array
|
||||
if ([item isKindOfClass:[NSString class]])
|
||||
{
|
||||
return Value([item UTF8String]);
|
||||
}
|
||||
|
||||
// add number value into array(such as int, float, bool and so on)
|
||||
// the value is a number
|
||||
if ([item isKindOfClass:[NSNumber class]])
|
||||
{
|
||||
NSNumber* num = item;
|
||||
const char* numType = [num objCType];
|
||||
if(num == (void*)kCFBooleanFalse || num == (void*)kCFBooleanTrue)
|
||||
{
|
||||
bool v = [num boolValue];
|
||||
return Value(v);
|
||||
}
|
||||
else if(strcmp(numType, @encode(float)) == 0)
|
||||
{
|
||||
return Value([num floatValue]);
|
||||
}
|
||||
else if(strcmp(numType, @encode(double)) == 0)
|
||||
{
|
||||
return Value([num doubleValue]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Value([num intValue]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// add dictionary value into array
|
||||
if ([item isKindOfClass:[NSDictionary class]])
|
||||
{
|
||||
ValueMap dict;
|
||||
for (id subKey in [item allKeys])
|
||||
{
|
||||
id subValue = [item objectForKey:subKey];
|
||||
addNSObjectToCCMap(subKey, subValue, dict);
|
||||
}
|
||||
|
||||
return Value(dict);
|
||||
}
|
||||
|
||||
// add array value into array
|
||||
if ([item isKindOfClass:[NSArray class]])
|
||||
{
|
||||
ValueVector subArray;
|
||||
for (id subItem in item)
|
||||
{
|
||||
addNSObjectToCCVector(subItem, subArray);
|
||||
}
|
||||
return Value(subArray);
|
||||
}
|
||||
|
||||
return Value::Null;
|
||||
}
|
||||
|
||||
static void addNSObjectToCCVector(id item, ValueVector& array)
|
||||
{
|
||||
array.push_back(convertNSObjectToCCValue(item));
|
||||
}
|
||||
|
||||
static void addCCValueToNSArray(const Value& value, NSMutableArray *array)
|
||||
{
|
||||
[array addObject:convertCCValueToNSObject(value)];
|
||||
}
|
||||
|
||||
static void addNSObjectToCCMap(id nsKey, id nsValue, ValueMap& dict)
|
||||
{
|
||||
// the key must be a string
|
||||
CCASSERT([nsKey isKindOfClass:[NSString class]], "The key should be a string!");
|
||||
std::string key = [nsKey UTF8String];
|
||||
dict[key] = convertNSObjectToCCValue(nsValue);
|
||||
}
|
||||
|
||||
static void addCCValueToNSDictionary(const std::string& key, const Value& value, NSMutableDictionary *dict)
|
||||
{
|
||||
NSString *NSkey = [NSString stringWithCString:key.c_str() encoding:NSUTF8StringEncoding];
|
||||
[dict setObject:convertCCValueToNSObject(value) forKey:NSkey];
|
||||
}
|
||||
|
||||
|
||||
FileUtilsApple::FileUtilsApple() : pimpl_(new IMPL([NSBundle mainBundle])) {
|
||||
}
|
||||
|
||||
FileUtilsApple::~FileUtilsApple() = default;
|
||||
|
||||
#if CC_FILEUTILS_APPLE_ENABLE_OBJC
|
||||
void FileUtilsApple::setBundle(NSBundle* bundle) {
|
||||
pimpl_->setBundle(bundle);
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma mark - FileUtils
|
||||
|
||||
static NSFileManager* s_fileManager = [NSFileManager defaultManager];
|
||||
|
||||
FileUtils* FileUtils::getInstance()
|
||||
{
|
||||
if (s_sharedFileUtils == nullptr)
|
||||
{
|
||||
s_sharedFileUtils = new (std::nothrow) FileUtilsApple();
|
||||
if(!s_sharedFileUtils->init())
|
||||
{
|
||||
delete s_sharedFileUtils;
|
||||
s_sharedFileUtils = nullptr;
|
||||
CCLOG("ERROR: Could not init CCFileUtilsApple");
|
||||
}
|
||||
}
|
||||
return s_sharedFileUtils;
|
||||
}
|
||||
|
||||
|
||||
std::string FileUtilsApple::getWritablePath() const
|
||||
{
|
||||
if (_writablePath.length())
|
||||
{
|
||||
return _writablePath;
|
||||
}
|
||||
|
||||
// save to document folder
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *documentsDirectory = [paths objectAtIndex:0];
|
||||
std::string strRet = [documentsDirectory UTF8String];
|
||||
strRet.append("/");
|
||||
return strRet;
|
||||
}
|
||||
|
||||
bool FileUtilsApple::isFileExistInternal(const std::string& filePath) const
|
||||
{
|
||||
if (filePath.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
|
||||
if (filePath[0] != '/')
|
||||
{
|
||||
std::string path;
|
||||
std::string file;
|
||||
size_t pos = filePath.find_last_of("/");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
file = filePath.substr(pos+1);
|
||||
path = filePath.substr(0, pos+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
file = filePath;
|
||||
}
|
||||
|
||||
NSString* fullpath = [pimpl_->getBundle() pathForResource:[NSString stringWithUTF8String:file.c_str()]
|
||||
ofType:nil
|
||||
inDirectory:[NSString stringWithUTF8String:path.c_str()]];
|
||||
if (fullpath != nil) {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search path is an absolute path.
|
||||
if ([s_fileManager fileExistsAtPath:[NSString stringWithUTF8String:filePath.c_str()]]) {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
|
||||
{
|
||||
auto ret = remove(fpath);
|
||||
if (ret)
|
||||
{
|
||||
log("Fail to remove: %s ",fpath);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool FileUtilsApple::removeDirectory(const std::string& path)
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
CCLOGERROR("Fail to remove directory, path is empty!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nftw(path.c_str(),unlink_cb, 64, FTW_DEPTH | FTW_PHYS))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string FileUtilsApple::getFullPathForDirectoryAndFilename(const std::string& directory, const std::string& filename) const
|
||||
{
|
||||
if (directory[0] != '/')
|
||||
{
|
||||
NSString* dirStr = [NSString stringWithUTF8String:directory.c_str()];
|
||||
// The following logic is used for remove the "../" in the directory
|
||||
// Because method "pathForResource" will return nil if the directory contains "../".
|
||||
auto theIdx = directory.find("..");
|
||||
if (theIdx != std::string::npos && theIdx > 0) {
|
||||
NSMutableArray<NSString *>* pathComps = [NSMutableArray arrayWithArray:[dirStr pathComponents]];
|
||||
NSUInteger idx = [pathComps indexOfObject:@".."];
|
||||
while (idx != NSNotFound && idx > 0) { // if found ".." & it's not at the beginning of the string
|
||||
[pathComps removeObjectAtIndex: idx]; // remove the item ".."
|
||||
[pathComps removeObjectAtIndex: idx - 1]; // remove the item before ".."
|
||||
idx = [pathComps indexOfObject:@".."]; // find ".." again
|
||||
}
|
||||
dirStr = [NSString pathWithComponents:pathComps];
|
||||
}
|
||||
|
||||
NSString* fullpath = [pimpl_->getBundle() pathForResource:[NSString stringWithUTF8String:filename.c_str()]
|
||||
ofType:nil
|
||||
inDirectory:dirStr];
|
||||
if (fullpath != nil) {
|
||||
return [fullpath UTF8String];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string fullPath = directory+filename;
|
||||
// Search path is an absolute path.
|
||||
if ([s_fileManager fileExistsAtPath:[NSString stringWithUTF8String:fullPath.c_str()]]) {
|
||||
return fullPath;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
ValueMap FileUtilsApple::getValueMapFromFile(const std::string& filename)
|
||||
{
|
||||
auto d(FileUtils::getInstance()->getDataFromFile(filename));
|
||||
return getValueMapFromData(reinterpret_cast<char*>(d.getBytes()), static_cast<int>(d.getSize()));
|
||||
}
|
||||
|
||||
ValueMap FileUtilsApple::getValueMapFromData(const char* filedata, int filesize)
|
||||
{
|
||||
NSData* file = [NSData dataWithBytes:filedata length:filesize];
|
||||
NSPropertyListFormat format;
|
||||
NSError* error;
|
||||
NSDictionary* dict = [NSPropertyListSerialization propertyListWithData:file options:NSPropertyListImmutable format:&format error:&error];
|
||||
|
||||
ValueMap ret;
|
||||
|
||||
if (dict != nil)
|
||||
{
|
||||
for (id key in [dict allKeys])
|
||||
{
|
||||
id value = [dict objectForKey:key];
|
||||
addNSObjectToCCMap(key, value, ret);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool FileUtilsApple::writeToFile(const ValueMap& dict, const std::string &fullPath)
|
||||
{
|
||||
return writeValueMapToFile(dict, fullPath);
|
||||
}
|
||||
|
||||
bool FileUtils::writeValueMapToFile(const ValueMap& dict, const std::string& fullPath)
|
||||
{
|
||||
valueMapCompact(const_cast<ValueMap&>(dict));
|
||||
//CCLOG("iOS||Mac Dictionary %d write to file %s", dict->_ID, fullPath.c_str());
|
||||
NSMutableDictionary *nsDict = [NSMutableDictionary dictionary];
|
||||
|
||||
for (auto iter = dict.begin(); iter != dict.end(); ++iter)
|
||||
{
|
||||
addCCValueToNSDictionary(iter->first, iter->second, nsDict);
|
||||
}
|
||||
|
||||
NSString *file = [NSString stringWithUTF8String:fullPath.c_str()];
|
||||
// do it atomically
|
||||
return [nsDict writeToFile:file atomically:YES];
|
||||
}
|
||||
|
||||
void FileUtilsApple::valueMapCompact(ValueMap& valueMap)
|
||||
{
|
||||
auto itr = valueMap.begin();
|
||||
while(itr != valueMap.end()){
|
||||
auto vtype = itr->second.getType();
|
||||
switch(vtype){
|
||||
case Value::Type::NONE:{
|
||||
itr = valueMap.erase(itr);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case Value::Type::MAP:{
|
||||
valueMapCompact(itr->second.asValueMap());
|
||||
}
|
||||
break;
|
||||
case Value::Type::VECTOR:{
|
||||
valueVectorCompact(itr->second.asValueVector());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
itr++;
|
||||
}
|
||||
}
|
||||
|
||||
void FileUtilsApple::valueVectorCompact(ValueVector& valueVector)
|
||||
{
|
||||
auto itr = valueVector.begin();
|
||||
while(itr != valueVector.end()){
|
||||
auto vtype = (*itr).getType();
|
||||
switch(vtype){
|
||||
case Value::Type::NONE:{
|
||||
itr = valueVector.erase(itr);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case Value::Type::MAP:{
|
||||
valueMapCompact((*itr).asValueMap());
|
||||
}
|
||||
break;
|
||||
case Value::Type::VECTOR:{
|
||||
valueVectorCompact((*itr).asValueVector());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
itr++;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileUtils::writeValueVectorToFile(const ValueVector& vecData, const std::string& fullPath)
|
||||
{
|
||||
NSString* path = [NSString stringWithUTF8String:fullPath.c_str()];
|
||||
NSMutableArray* array = [NSMutableArray array];
|
||||
|
||||
for (const auto &e : vecData)
|
||||
{
|
||||
addCCValueToNSArray(e, array);
|
||||
}
|
||||
|
||||
[array writeToFile:path atomically:YES];
|
||||
|
||||
return true;
|
||||
}
|
||||
ValueVector FileUtilsApple::getValueVectorFromFile(const std::string& filename)
|
||||
{
|
||||
// NSString* pPath = [NSString stringWithUTF8String:pFileName];
|
||||
// NSString* pathExtension= [pPath pathExtension];
|
||||
// pPath = [pPath stringByDeletingPathExtension];
|
||||
// pPath = [[NSBundle mainBundle] pathForResource:pPath ofType:pathExtension];
|
||||
// fixing cannot read data using Array::createWithContentsOfFile
|
||||
std::string fullPath = fullPathForFilename(filename);
|
||||
NSString* path = [NSString stringWithUTF8String:fullPath.c_str()];
|
||||
NSArray* array = [NSArray arrayWithContentsOfFile:path];
|
||||
|
||||
ValueVector ret;
|
||||
|
||||
for (id value in array)
|
||||
{
|
||||
addNSObjectToCCVector(value, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool FileUtilsApple::createDirectory(const std::string& path)
|
||||
{
|
||||
CCASSERT(!path.empty(), "Invalid path");
|
||||
|
||||
if (isDirectoryExist(path))
|
||||
return true;
|
||||
|
||||
NSError* error;
|
||||
|
||||
bool result = [s_fileManager createDirectoryAtPath:[NSString stringWithUTF8String:path.c_str()] withIntermediateDirectories:YES attributes:nil error:&error];
|
||||
|
||||
if(!result && error != nil)
|
||||
{
|
||||
CCLOGERROR("Fail to create directory \"%s\": %s", path.c_str(), [error.localizedDescription UTF8String]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
567
cocos2d-x/cocos/platform/desktop/CCGLView-desktop.cpp
Normal file
567
cocos2d-x/cocos/platform/desktop/CCGLView-desktop.cpp
Normal file
@@ -0,0 +1,567 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "platform/desktop/CCGLView-desktop.h"
|
||||
#include "scripting/js-bindings/event/EventDispatcher.h"
|
||||
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "base/ccMacros.h"
|
||||
#include "base/ccUtils.h"
|
||||
#include "platform/CCApplication.h"
|
||||
#include "cocos/ui/edit-box/EditBox.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <unordered_map>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
GLView* GLFWEventHandler::_view = nullptr;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct RGBA
|
||||
{
|
||||
int r = 0;
|
||||
int g = 0;
|
||||
int b = 0;
|
||||
int a = 0;
|
||||
};
|
||||
|
||||
struct DepthInfo
|
||||
{
|
||||
int depth = 0;
|
||||
int stencil = 0;
|
||||
};
|
||||
|
||||
struct RGBA pixelformat2RGBA(Application::PixelFormat pixelformat)
|
||||
{
|
||||
struct RGBA ret;
|
||||
if (Application::PixelFormat::RGBA8 == pixelformat)
|
||||
ret.r = ret.g = ret.b = ret. a = 8;
|
||||
|
||||
if (Application::PixelFormat::RGB565 == pixelformat)
|
||||
{
|
||||
ret.r = 5;
|
||||
ret.g = 6;
|
||||
ret.b = 5;
|
||||
}
|
||||
|
||||
if (Application::PixelFormat::RGB8 == pixelformat)
|
||||
ret.r = ret.g = ret.b = 8;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct DepthInfo depthformat2DepthInfo(Application::DepthFormat depthFormat)
|
||||
{
|
||||
struct DepthInfo ret;
|
||||
switch (depthFormat)
|
||||
{
|
||||
case Application::DepthFormat::NONE:
|
||||
break;
|
||||
case Application::DepthFormat::DEPTH_COMPONENT16:
|
||||
ret.depth = 16;
|
||||
break;
|
||||
case Application::DepthFormat::DEPTH_COMPONENT24:
|
||||
ret.depth = 24;
|
||||
break;
|
||||
case Application::DepthFormat::DEPTH_COMPONENT32F:
|
||||
ret.depth = 32;
|
||||
break;
|
||||
case Application::DepthFormat::DEPTH24_STENCIL8:
|
||||
ret.depth = 24;
|
||||
ret.stencil = 8;
|
||||
break;
|
||||
case Application::DepthFormat::DEPTH32F_STENCIL8:
|
||||
ret.depth = 32;
|
||||
ret.stencil = 8;
|
||||
break;
|
||||
case Application::DepthFormat::STENCIL_INDEX8:
|
||||
ret.stencil = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// implement GLView
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLView::GLView(Application* application, const std::string& name, int x, int y, int width, int height,
|
||||
Application::PixelFormat pixelformat, Application::DepthFormat depthFormat, int multisamplingCount)
|
||||
: _application(application)
|
||||
, _mainWindow(nullptr)
|
||||
, _monitor(nullptr)
|
||||
, _mouseX(0.0f)
|
||||
, _mouseY(0.0f)
|
||||
{
|
||||
GLFWEventHandler::setGLView(this);
|
||||
glfwSetErrorCallback(GLFWEventHandler::onGLFWError);
|
||||
glfwInit();
|
||||
|
||||
struct RGBA rgba = pixelformat2RGBA(pixelformat);
|
||||
struct DepthInfo depthInfo = depthformat2DepthInfo(depthFormat);
|
||||
|
||||
glfwWindowHint(GLFW_RED_BITS, rgba.r);
|
||||
glfwWindowHint(GLFW_GREEN_BITS, rgba.g);
|
||||
glfwWindowHint(GLFW_BLUE_BITS, rgba.b);
|
||||
glfwWindowHint(GLFW_ALPHA_BITS, rgba.a);
|
||||
glfwWindowHint(GLFW_DEPTH_BITS, depthInfo.depth);
|
||||
glfwWindowHint(GLFW_STENCIL_BITS, depthInfo.stencil);
|
||||
glfwWindowHint(GLFW_SAMPLES, multisamplingCount);
|
||||
_mainWindow = glfwCreateWindow(width, height, name.c_str(), _monitor, nullptr);
|
||||
|
||||
if (_mainWindow == nullptr)
|
||||
{
|
||||
std::string message = "Can't create window";
|
||||
if (!_glfwError.empty())
|
||||
{
|
||||
message.append("\nMore info: \n");
|
||||
message.append(_glfwError);
|
||||
}
|
||||
printf("%s\n", message.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(_mainWindow);
|
||||
|
||||
glfwSetMouseButtonCallback(_mainWindow, GLFWEventHandler::onGLFWMouseCallBack);
|
||||
glfwSetCursorPosCallback(_mainWindow, GLFWEventHandler::onGLFWMouseMoveCallBack);
|
||||
glfwSetScrollCallback(_mainWindow, GLFWEventHandler::onGLFWMouseScrollCallback);
|
||||
glfwSetCharCallback(_mainWindow, GLFWEventHandler::onGLFWCharCallback);
|
||||
glfwSetKeyCallback(_mainWindow, GLFWEventHandler::onGLFWKeyCallback);
|
||||
glfwSetWindowIconifyCallback(_mainWindow, GLFWEventHandler::onGLFWWindowIconifyCallback);
|
||||
glfwSetWindowSizeCallback(_mainWindow, GLFWEventHandler::onGLFWWindowSizeFunCallback);
|
||||
|
||||
// check OpenGL version at first
|
||||
const GLubyte* glVersion = glGetString(GL_VERSION);
|
||||
|
||||
if (utils::atof((const char*)glVersion) < 1.5 )
|
||||
{
|
||||
char strComplain[256] = {0};
|
||||
sprintf(strComplain,
|
||||
"OpenGL 1.5 or higher is required (your version is %s). Please upgrade the driver of your video card.",
|
||||
glVersion);
|
||||
printf("%s\n", strComplain);
|
||||
return;
|
||||
}
|
||||
|
||||
initGlew();
|
||||
|
||||
// Enable point size by default.
|
||||
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||
|
||||
if(multisamplingCount > 0)
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
computeScale();
|
||||
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_mainFBO);
|
||||
Application::getInstance()->updateViewSize(width * _scale, height * _scale);
|
||||
}
|
||||
|
||||
GLView::~GLView()
|
||||
{
|
||||
GLFWEventHandler::setGLView(nullptr);
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
bool GLView::windowShouldClose() const
|
||||
{
|
||||
if(_mainWindow)
|
||||
return glfwWindowShouldClose(_mainWindow) ? true : false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLView::pollEvents()
|
||||
{
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
void GLView::swapBuffers()
|
||||
{
|
||||
glfwSwapBuffers(_mainWindow);
|
||||
}
|
||||
|
||||
float GLView::getScale() const
|
||||
{
|
||||
return _scale;
|
||||
}
|
||||
|
||||
GLint GLView::getMainFBO() const
|
||||
{
|
||||
return _mainFBO;
|
||||
}
|
||||
|
||||
void GLView::setIsEditboxEditing(bool value)
|
||||
{
|
||||
_isEditboxEditing = value;
|
||||
}
|
||||
|
||||
void GLView::onGLFWError(int errorID, const char* errorDesc)
|
||||
{
|
||||
if (_mainWindow)
|
||||
printf("GLFWError #%d Happen, %s\n", errorID, errorDesc);
|
||||
else
|
||||
printf("GLFWError #%d Happen, %s\n", errorID, errorDesc);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
void dispatchMouseEvent(double x, double y, unsigned short button, cocos2d::MouseEvent::Type type)
|
||||
{
|
||||
cocos2d::MouseEvent mouseEvent;
|
||||
mouseEvent.x = x;
|
||||
mouseEvent.y = y;
|
||||
mouseEvent.button = button;
|
||||
mouseEvent.type = type;
|
||||
cocos2d::EventDispatcher::dispatchMouseEvent(mouseEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void GLView::onGLFWMouseCallBack(GLFWwindow* /*window*/, int button, int action, int /*modify*/)
|
||||
{
|
||||
if (_isEditboxEditing)
|
||||
EditBox::complete();
|
||||
|
||||
unsigned short jsButton;
|
||||
if (GLFW_MOUSE_BUTTON_LEFT == button)
|
||||
jsButton = 0;
|
||||
else if (GLFW_MOUSE_BUTTON_MIDDLE == button)
|
||||
jsButton = 1;
|
||||
else if (GLFW_MOUSE_BUTTON_RIGHT == button)
|
||||
jsButton = 2;
|
||||
|
||||
if (GLFW_PRESS == action)
|
||||
{
|
||||
dispatchMouseEvent(_mouseX, _mouseY, jsButton, MouseEvent::Type::DOWN);
|
||||
}
|
||||
else if (GLFW_RELEASE == action)
|
||||
{
|
||||
dispatchMouseEvent(_mouseX, _mouseY, jsButton, MouseEvent::Type::UP);
|
||||
}
|
||||
}
|
||||
|
||||
void GLView::onGLFWMouseScrollCallback(GLFWwindow* window, double x, double y)
|
||||
{
|
||||
if (_isEditboxEditing)
|
||||
return;
|
||||
|
||||
dispatchMouseEvent(x, y, 0, MouseEvent::Type::WHEEL);
|
||||
}
|
||||
|
||||
void GLView::onGLFWMouseMoveCallBack(GLFWwindow* window, double x, double y)
|
||||
{
|
||||
_mouseX = (float)x;
|
||||
_mouseY = (float)y;
|
||||
|
||||
if (_isEditboxEditing)
|
||||
return;
|
||||
|
||||
dispatchMouseEvent(_mouseX, _mouseY, 0, MouseEvent::Type::MOVE);
|
||||
}
|
||||
|
||||
void GLView::onGLFWKeyCallback(GLFWwindow* /*window*/, int key, int /*scancode*/, int action, int mods)
|
||||
{
|
||||
// printf("key: %d, action: %d, mods: %d\n", key, action, mods);
|
||||
int keyInWeb = -1;
|
||||
if (key >= GLFW_KEY_0 && key <= GLFW_KEY_9)
|
||||
keyInWeb = key;
|
||||
else if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z)
|
||||
keyInWeb = key;
|
||||
else if (key >= GLFW_KEY_F1 && key <= GLFW_KEY_F12)
|
||||
keyInWeb = key - 178;
|
||||
else if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_9)
|
||||
keyInWeb = key - 272 + 10000; // For indicating number in Numberpad, needs to be converted in JS.
|
||||
else if (key == GLFW_KEY_ESCAPE)
|
||||
keyInWeb = 27;
|
||||
else if (key == GLFW_KEY_MINUS)
|
||||
keyInWeb = 189;
|
||||
else if (key == GLFW_KEY_EQUAL)
|
||||
keyInWeb = 187;
|
||||
else if (key == GLFW_KEY_BACKSLASH)
|
||||
keyInWeb = 220;
|
||||
else if (key == GLFW_KEY_GRAVE_ACCENT)
|
||||
keyInWeb = 192;
|
||||
else if (key == GLFW_KEY_BACKSPACE)
|
||||
keyInWeb = 8;
|
||||
else if (key == GLFW_KEY_ENTER)
|
||||
keyInWeb = 13;
|
||||
else if (key == GLFW_KEY_LEFT_BRACKET)
|
||||
keyInWeb = 219;
|
||||
else if (key == GLFW_KEY_RIGHT_BRACKET)
|
||||
keyInWeb = 221;
|
||||
else if (key == GLFW_KEY_SEMICOLON)
|
||||
keyInWeb = 186;
|
||||
else if (key == GLFW_KEY_APOSTROPHE)
|
||||
keyInWeb = 222;
|
||||
else if (key == GLFW_KEY_TAB)
|
||||
keyInWeb = 9;
|
||||
else if (key == GLFW_KEY_LEFT_CONTROL)
|
||||
keyInWeb = 17;
|
||||
else if (key == GLFW_KEY_RIGHT_CONTROL)
|
||||
keyInWeb = 17 + 20000; // For indicating Left/Right control, needs to be converted in JS.
|
||||
else if (key == GLFW_KEY_LEFT_SHIFT)
|
||||
keyInWeb = 16;
|
||||
else if (key == GLFW_KEY_RIGHT_SHIFT)
|
||||
keyInWeb = 16 + 20000; // For indicating Left/Right shift, needs to be converted in JS.
|
||||
else if (key == GLFW_KEY_LEFT_ALT)
|
||||
keyInWeb = 18;
|
||||
else if (key == GLFW_KEY_RIGHT_ALT)
|
||||
keyInWeb = 18 + 20000; // For indicating Left/Right alt, needs to be converted in JS.
|
||||
else if (key == GLFW_KEY_LEFT_SUPER)
|
||||
keyInWeb = 91;
|
||||
else if (key == GLFW_KEY_RIGHT_SUPER)
|
||||
keyInWeb = 93;
|
||||
else if (key == GLFW_KEY_UP)
|
||||
keyInWeb = 38;
|
||||
else if (key == GLFW_KEY_DOWN)
|
||||
keyInWeb = 40;
|
||||
else if (key == GLFW_KEY_LEFT)
|
||||
keyInWeb = 37;
|
||||
else if (key == GLFW_KEY_RIGHT)
|
||||
keyInWeb = 39;
|
||||
else if (key == GLFW_KEY_MENU)
|
||||
keyInWeb = 93 + 20000;
|
||||
else if (key == GLFW_KEY_KP_ENTER)
|
||||
keyInWeb = 13 + 20000; // For indicating numpad enter, needs to be converted in JS.
|
||||
else if (key == GLFW_KEY_KP_ADD)
|
||||
keyInWeb = 107;
|
||||
else if (key == GLFW_KEY_KP_SUBTRACT)
|
||||
keyInWeb = 109;
|
||||
else if (key == GLFW_KEY_KP_MULTIPLY)
|
||||
keyInWeb = 106;
|
||||
else if (key == GLFW_KEY_KP_DIVIDE)
|
||||
keyInWeb = 111;
|
||||
else if (key == GLFW_KEY_NUM_LOCK)
|
||||
keyInWeb = 12;
|
||||
else if (key == GLFW_KEY_F13)
|
||||
keyInWeb = 124;
|
||||
else if (key == GLFW_KEY_BACKSPACE)
|
||||
keyInWeb = 8;
|
||||
else if (key == GLFW_KEY_HOME)
|
||||
keyInWeb = 36;
|
||||
else if (key == GLFW_KEY_PAGE_UP)
|
||||
keyInWeb = 33;
|
||||
else if (key == GLFW_KEY_PAGE_DOWN)
|
||||
keyInWeb = 34;
|
||||
else if (key == GLFW_KEY_END)
|
||||
keyInWeb = 35;
|
||||
else if (key == GLFW_KEY_COMMA)
|
||||
keyInWeb = 188;
|
||||
else if (key == GLFW_KEY_PERIOD)
|
||||
keyInWeb = 190;
|
||||
else if (key == GLFW_KEY_SLASH)
|
||||
keyInWeb = 191;
|
||||
else if (key == GLFW_KEY_SPACE)
|
||||
keyInWeb = 32;
|
||||
else if (key == GLFW_KEY_DELETE)
|
||||
keyInWeb = 46;
|
||||
else if (key == GLFW_KEY_KP_DECIMAL)
|
||||
keyInWeb = 110;
|
||||
else if (key == GLFW_KEY_CAPS_LOCK)
|
||||
keyInWeb = 20;
|
||||
|
||||
KeyboardEvent event;
|
||||
event.key = keyInWeb;
|
||||
if (action == GLFW_PRESS)
|
||||
event.action = KeyboardEvent::Action::PRESS;
|
||||
else if (action == GLFW_RELEASE)
|
||||
event.action = KeyboardEvent::Action::RELEASE;
|
||||
else if (action == GLFW_REPEAT)
|
||||
event.action = KeyboardEvent::Action::REPEAT;
|
||||
|
||||
if (mods & GLFW_MOD_SHIFT)
|
||||
event.shiftKeyActive = true;
|
||||
if (mods & GLFW_MOD_CONTROL)
|
||||
event.ctrlKeyActive = true;
|
||||
if (mods & GLFW_MOD_ALT)
|
||||
event.altKeyActive = true;
|
||||
if (mods & GLFW_MOD_SUPER)
|
||||
event.metaKeyActive = true;
|
||||
|
||||
EventDispatcher::dispatchKeyboardEvent(event);
|
||||
}
|
||||
|
||||
void GLView::onGLFWCharCallback(GLFWwindow* /*window*/, unsigned int character)
|
||||
{
|
||||
// REFINE
|
||||
// char16_t wcharString[2] = { (char16_t) character, 0 };
|
||||
// std::string utf8String;
|
||||
|
||||
// StringUtils::UTF16ToUTF8( wcharString, utf8String );
|
||||
// static std::set<std::string> controlUnicode = {
|
||||
// "\xEF\x9C\x80", // up
|
||||
// "\xEF\x9C\x81", // down
|
||||
// "\xEF\x9C\x82", // left
|
||||
// "\xEF\x9C\x83", // right
|
||||
// "\xEF\x9C\xA8", // delete
|
||||
// "\xEF\x9C\xA9", // home
|
||||
// "\xEF\x9C\xAB", // end
|
||||
// "\xEF\x9C\xAC", // pageup
|
||||
// "\xEF\x9C\xAD", // pagedown
|
||||
// "\xEF\x9C\xB9" // clear
|
||||
// };
|
||||
}
|
||||
|
||||
void GLView::onGLFWWindowIconifyCallback(GLFWwindow* /*window*/, int iconified)
|
||||
{
|
||||
if (iconified == GL_TRUE)
|
||||
_application->onPause();
|
||||
else
|
||||
_application->onResume();
|
||||
}
|
||||
|
||||
void GLView::onGLFWWindowSizeFunCallback(GLFWwindow *window, int width, int height)
|
||||
{
|
||||
int targetWidth = width * _scale, targetHeight = height * _scale;
|
||||
Application::getInstance()->updateViewSize(targetWidth, targetHeight);
|
||||
EventDispatcher::dispatchResizeEvent(targetWidth, targetHeight);
|
||||
}
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
||||
static bool glew_dynamic_binding()
|
||||
{
|
||||
const char *gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
|
||||
|
||||
// If the current opengl driver doesn't have framebuffers methods, check if an extension exists
|
||||
if (glGenFramebuffers == nullptr)
|
||||
{
|
||||
log("OpenGL: glGenFramebuffers is nullptr, try to detect an extension");
|
||||
if (strstr(gl_extensions, "ARB_framebuffer_object"))
|
||||
{
|
||||
log("OpenGL: ARB_framebuffer_object is supported");
|
||||
|
||||
glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) wglGetProcAddress("glIsRenderbuffer");
|
||||
glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) wglGetProcAddress("glBindRenderbuffer");
|
||||
glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) wglGetProcAddress("glDeleteRenderbuffers");
|
||||
glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) wglGetProcAddress("glGenRenderbuffers");
|
||||
glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) wglGetProcAddress("glRenderbufferStorage");
|
||||
glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) wglGetProcAddress("glGetRenderbufferParameteriv");
|
||||
glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) wglGetProcAddress("glIsFramebuffer");
|
||||
glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) wglGetProcAddress("glBindFramebuffer");
|
||||
glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) wglGetProcAddress("glDeleteFramebuffers");
|
||||
glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) wglGetProcAddress("glGenFramebuffers");
|
||||
glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) wglGetProcAddress("glCheckFramebufferStatus");
|
||||
glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) wglGetProcAddress("glFramebufferTexture1D");
|
||||
glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) wglGetProcAddress("glFramebufferTexture2D");
|
||||
glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) wglGetProcAddress("glFramebufferTexture3D");
|
||||
glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) wglGetProcAddress("glFramebufferRenderbuffer");
|
||||
glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) wglGetProcAddress("glGetFramebufferAttachmentParameteriv");
|
||||
glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) wglGetProcAddress("glGenerateMipmap");
|
||||
}
|
||||
else
|
||||
if (strstr(gl_extensions, "EXT_framebuffer_object"))
|
||||
{
|
||||
log("OpenGL: EXT_framebuffer_object is supported");
|
||||
glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) wglGetProcAddress("glIsRenderbufferEXT");
|
||||
glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) wglGetProcAddress("glBindRenderbufferEXT");
|
||||
glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) wglGetProcAddress("glDeleteRenderbuffersEXT");
|
||||
glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) wglGetProcAddress("glGenRenderbuffersEXT");
|
||||
glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) wglGetProcAddress("glRenderbufferStorageEXT");
|
||||
glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) wglGetProcAddress("glGetRenderbufferParameterivEXT");
|
||||
glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) wglGetProcAddress("glIsFramebufferEXT");
|
||||
glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) wglGetProcAddress("glBindFramebufferEXT");
|
||||
glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) wglGetProcAddress("glDeleteFramebuffersEXT");
|
||||
glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) wglGetProcAddress("glGenFramebuffersEXT");
|
||||
glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) wglGetProcAddress("glCheckFramebufferStatusEXT");
|
||||
glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) wglGetProcAddress("glFramebufferTexture1DEXT");
|
||||
glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) wglGetProcAddress("glFramebufferTexture2DEXT");
|
||||
glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) wglGetProcAddress("glFramebufferTexture3DEXT");
|
||||
glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) wglGetProcAddress("glFramebufferRenderbufferEXT");
|
||||
glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) wglGetProcAddress("glGetFramebufferAttachmentParameterivEXT");
|
||||
glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) wglGetProcAddress("glGenerateMipmapEXT");
|
||||
}
|
||||
else
|
||||
{
|
||||
log("OpenGL: No framebuffers extension is supported");
|
||||
log("OpenGL: Any call to Fbo will crash!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void GLView::computeScale()
|
||||
{
|
||||
int widthInPixel = 0;
|
||||
glfwGetFramebufferSize(_mainWindow, &widthInPixel, nullptr);
|
||||
|
||||
int width = 0;
|
||||
glfwGetWindowSize(_mainWindow, &width, nullptr);
|
||||
|
||||
_scale = float(widthInPixel) / width;
|
||||
}
|
||||
|
||||
// helper
|
||||
bool GLView::initGlew()
|
||||
{
|
||||
#if (CC_TARGET_PLATFORM != CC_PLATFORM_MAC)
|
||||
GLenum GlewInitResult = glewInit();
|
||||
if (GLEW_OK != GlewInitResult)
|
||||
{
|
||||
log((char *)glewGetErrorString(GlewInitResult), "OpenGL error");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
|
||||
{
|
||||
log("Ready for GLSL");
|
||||
}
|
||||
else
|
||||
{
|
||||
log("Not totally ready :(");
|
||||
}
|
||||
|
||||
if (glewIsSupported("GL_VERSION_2_0"))
|
||||
{
|
||||
log("Ready for OpenGL 2.0");
|
||||
}
|
||||
else
|
||||
{
|
||||
log("OpenGL 2.0 not supported");
|
||||
}
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
||||
if(glew_dynamic_binding() == false)
|
||||
{
|
||||
log("No OpenGL framebuffer support. Please upgrade the driver of your video card.", "OpenGL error");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // (CC_TARGET_PLATFORM != CC_PLATFORM_MAC)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_CC_END // end of namespace cocos2d;
|
||||
159
cocos2d-x/cocos/platform/desktop/CCGLView-desktop.h
Normal file
159
cocos2d-x/cocos/platform/desktop/CCGLView-desktop.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "platform/CCGL.h"
|
||||
#include "base/ccMacros.h"
|
||||
#include "platform/CCApplication.h"
|
||||
|
||||
#include "glfw3/glfw3.h"
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
||||
#ifndef GLFW_EXPOSE_NATIVE_WIN32
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#endif
|
||||
#ifndef GLFW_EXPOSE_NATIVE_WGL
|
||||
#define GLFW_EXPOSE_NATIVE_WGL
|
||||
#endif
|
||||
#include "glfw3/glfw3native.h"
|
||||
#endif /* (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) */
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
|
||||
#ifndef GLFW_EXPOSE_NATIVE_NSGL
|
||||
#define GLFW_EXPOSE_NATIVE_NSGL
|
||||
#endif
|
||||
#ifndef GLFW_EXPOSE_NATIVE_COCOA
|
||||
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||
#endif
|
||||
#include "glfw3/glfw3native.h"
|
||||
#endif // #if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
class CC_DLL GLView final
|
||||
{
|
||||
public:
|
||||
GLView(Application *application, const std::string& name, int x, int y, int width, int height,
|
||||
Application::PixelFormat pixelformat, Application::DepthFormat depthFormat, int multiSampleCount);
|
||||
~GLView();
|
||||
|
||||
bool windowShouldClose() const;
|
||||
void pollEvents();
|
||||
void swapBuffers();
|
||||
float getScale() const;
|
||||
GLint getMainFBO() const;
|
||||
void setIsEditboxEditing(bool value);
|
||||
|
||||
inline GLFWwindow* getGLFWWindow() const {return _mainWindow;};
|
||||
|
||||
private:
|
||||
bool initGlew();
|
||||
void computeScale();
|
||||
|
||||
// GLFW callbacks
|
||||
void onGLFWError(int errorID, const char* errorDesc);
|
||||
void onGLFWMouseCallBack(GLFWwindow* window, int button, int action, int modify);
|
||||
void onGLFWMouseMoveCallBack(GLFWwindow* window, double x, double y);
|
||||
void onGLFWMouseScrollCallback(GLFWwindow* window, double x, double y);
|
||||
void onGLFWKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||
void onGLFWCharCallback(GLFWwindow* window, unsigned int character);
|
||||
void onGLFWWindowIconifyCallback(GLFWwindow* window, int iconified);
|
||||
void onGLFWWindowSizeFunCallback(GLFWwindow *window, int width, int height);
|
||||
|
||||
GLFWwindow* _mainWindow = nullptr;
|
||||
GLFWmonitor* _monitor = nullptr;
|
||||
GLint _mainFBO = -1;
|
||||
|
||||
std::string _glfwError;
|
||||
|
||||
Application *_application = nullptr;
|
||||
|
||||
float _mouseX = 0;
|
||||
float _mouseY = 0;
|
||||
|
||||
// (framebuffer size) / (window size)
|
||||
float _scale = 1.0f;
|
||||
|
||||
bool _isEditboxEditing = false;
|
||||
|
||||
friend class GLFWEventHandler;
|
||||
};
|
||||
|
||||
|
||||
class CC_DLL GLFWEventHandler final
|
||||
{
|
||||
public:
|
||||
static void onGLFWError(int errorID, const char* errorDesc)
|
||||
{
|
||||
_view->onGLFWError(errorID, errorDesc);
|
||||
}
|
||||
|
||||
static void onGLFWMouseCallBack(GLFWwindow* window, int button, int action, int modify)
|
||||
{
|
||||
_view->onGLFWMouseCallBack(window, button, action, modify);
|
||||
}
|
||||
|
||||
static void onGLFWMouseMoveCallBack(GLFWwindow* window, double x, double y)
|
||||
{
|
||||
_view->onGLFWMouseMoveCallBack(window, x, y);
|
||||
}
|
||||
|
||||
static void onGLFWMouseScrollCallback(GLFWwindow* window, double x, double y)
|
||||
{
|
||||
_view->onGLFWMouseScrollCallback(window, x, y);
|
||||
}
|
||||
|
||||
static void onGLFWKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
_view->onGLFWKeyCallback(window, key, scancode, action, mods);
|
||||
}
|
||||
|
||||
static void onGLFWCharCallback(GLFWwindow* window, unsigned int character)
|
||||
{
|
||||
_view->onGLFWCharCallback(window, character);
|
||||
}
|
||||
|
||||
static void setGLView(GLView* view)
|
||||
{
|
||||
_view = view;
|
||||
}
|
||||
|
||||
static void onGLFWWindowIconifyCallback(GLFWwindow* window, int iconified)
|
||||
{
|
||||
_view->onGLFWWindowIconifyCallback(window, iconified);
|
||||
}
|
||||
|
||||
static void onGLFWWindowSizeFunCallback(GLFWwindow *window, int width, int height)
|
||||
{
|
||||
_view->onGLFWWindowSizeFunCallback(window, width, height);
|
||||
}
|
||||
|
||||
private:
|
||||
static GLView* _view;
|
||||
};
|
||||
|
||||
NS_CC_END // end of namespace cocos2d
|
||||
533
cocos2d-x/cocos/platform/ios/CCApplication-ios.mm
Normal file
533
cocos2d-x/cocos/platform/ios/CCApplication-ios.mm
Normal file
@@ -0,0 +1,533 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2017 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#import "CCApplication.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
#include "base/CCScheduler.h"
|
||||
#include "base/CCAutoreleasePool.h"
|
||||
#include "base/CCGLUtils.h"
|
||||
#include "base/CCConfiguration.h"
|
||||
#include "renderer/gfx/DeviceGraphics.h"
|
||||
#include "scripting/js-bindings/event/EventDispatcher.h"
|
||||
#include "scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "CCEAGLView-ios.h"
|
||||
#include "base/CCGLUtils.h"
|
||||
#include "audio/include/AudioEngine.h"
|
||||
#include "platform/CCDevice.h"
|
||||
#include "cocos/renderer/gfx/DeviceGraphics.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
bool setCanvasCallback(se::Object* global)
|
||||
{
|
||||
auto &viewSize = cocos2d::Application::getInstance()->getViewSize();
|
||||
se::ScriptEngine* se = se::ScriptEngine::getInstance();
|
||||
uint8_t devicePixelRatio = cocos2d::Application::getInstance()->getDevicePixelRatio();
|
||||
int screenScale = cocos2d::Device::getDevicePixelRatio();
|
||||
char commandBuf[200] = {0};
|
||||
//set window.innerWidth/innerHeight in CSS pixel units, not physical pixel units.
|
||||
sprintf(commandBuf, "window.innerWidth = %d; window.innerHeight = %d;",
|
||||
(int)(viewSize.x / screenScale / devicePixelRatio),
|
||||
(int)(viewSize.y / screenScale / devicePixelRatio));
|
||||
se->evalString(commandBuf);
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@interface MainLoop : NSObject
|
||||
{
|
||||
id _displayLink;
|
||||
int _fps;
|
||||
float _systemVersion;
|
||||
BOOL _isAppActive;
|
||||
cocos2d::Device::Rotation _lastRotation;
|
||||
cocos2d::Application* _application;
|
||||
std::shared_ptr<cocos2d::Scheduler> _scheduler;
|
||||
}
|
||||
-(void) startMainLoop;
|
||||
-(void) stopMainLoop;
|
||||
-(void) doCaller: (id) sender;
|
||||
-(void) setPreferredFPS:(int)fps;
|
||||
-(void) firstStart:(id) view;
|
||||
@end
|
||||
|
||||
@implementation MainLoop
|
||||
|
||||
- (instancetype)initWithApplication:(cocos2d::Application*) application
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
_fps = 60;
|
||||
_systemVersion = [[UIDevice currentDevice].systemVersion floatValue];
|
||||
|
||||
_application = application;
|
||||
_scheduler = _application->getScheduler();
|
||||
|
||||
_lastRotation = cocos2d::Device::getDeviceRotation();
|
||||
_isAppActive = [UIApplication sharedApplication].applicationState == UIApplicationStateActive;
|
||||
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
||||
[nc addObserver:self selector:@selector(appDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
|
||||
[nc addObserver:self selector:@selector(appDidBecomeInactive) name:UIApplicationWillResignActiveNotification object:nil];
|
||||
|
||||
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
|
||||
[nc addObserver:self selector:@selector(statusBarOrientationChanged:)name:UIApplicationDidChangeStatusBarOrientationNotification
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) statusBarOrientationChanged:(NSNotification *)note
|
||||
{
|
||||
cocos2d::Device::Rotation rotation = cocos2d::Device::Rotation::_0;
|
||||
UIDevice * device = [UIDevice currentDevice];
|
||||
|
||||
// NOTE: https://developer.apple.com/documentation/uikit/uideviceorientation
|
||||
// when the device rotates to LandscapeLeft, device.orientation returns UIDeviceOrientationLandscapeRight
|
||||
// when the device rotates to LandscapeRight, device.orientation returns UIDeviceOrientationLandscapeLeft
|
||||
switch(device.orientation)
|
||||
{
|
||||
case UIDeviceOrientationPortrait:
|
||||
rotation = cocos2d::Device::Rotation::_0;
|
||||
break;
|
||||
case UIDeviceOrientationLandscapeLeft:
|
||||
rotation = cocos2d::Device::Rotation::_90;
|
||||
break;
|
||||
case UIDeviceOrientationPortraitUpsideDown:
|
||||
rotation = cocos2d::Device::Rotation::_180;
|
||||
break;
|
||||
case UIDeviceOrientationLandscapeRight:
|
||||
rotation = cocos2d::Device::Rotation::_270;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
if(_lastRotation != rotation){
|
||||
cocos2d::EventDispatcher::dispatchOrientationChangeEvent((int) rotation);
|
||||
_lastRotation = rotation;
|
||||
}
|
||||
|
||||
CGRect bounds = [UIScreen mainScreen].bounds;
|
||||
float scale = [[UIScreen mainScreen] scale];
|
||||
float width = bounds.size.width * scale;
|
||||
float height = bounds.size.height * scale;
|
||||
cocos2d::Application::getInstance()->updateViewSize(width, height);
|
||||
}
|
||||
|
||||
-(void) dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[_displayLink release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)appDidBecomeActive
|
||||
{
|
||||
_isAppActive = YES;
|
||||
}
|
||||
|
||||
- (void)appDidBecomeInactive
|
||||
{
|
||||
_isAppActive = NO;
|
||||
}
|
||||
|
||||
-(void) firstStart:(id) view
|
||||
{
|
||||
if ([view isReady])
|
||||
{
|
||||
auto scheduler = _application->getScheduler();
|
||||
scheduler->removeAllFunctionsToBePerformedInCocosThread();
|
||||
scheduler->unscheduleAll();
|
||||
|
||||
se::ScriptEngine::getInstance()->cleanup();
|
||||
cocos2d::PoolManager::getInstance()->getCurrentPool()->clear();
|
||||
cocos2d::EventDispatcher::init();
|
||||
|
||||
cocos2d::ccInvalidateStateCache();
|
||||
se::ScriptEngine* se = se::ScriptEngine::getInstance();
|
||||
se->addRegisterCallback(setCanvasCallback);
|
||||
|
||||
if(!_application->applicationDidFinishLaunching())
|
||||
return;
|
||||
|
||||
[self startMainLoop];
|
||||
}
|
||||
else
|
||||
// Replace performSelector usage for Apple review policy
|
||||
// https://github.com/cocos-creator/3d-tasks/issues/9770
|
||||
// [self performSelector:@selector(firstStart:) withObject:view afterDelay:0];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self firstStart:view];
|
||||
});
|
||||
}
|
||||
|
||||
-(void) startMainLoop
|
||||
{
|
||||
[self stopMainLoop];
|
||||
|
||||
_displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doCaller:)];
|
||||
if (_systemVersion >= 10.0f)
|
||||
[_displayLink setPreferredFramesPerSecond: _fps];
|
||||
else
|
||||
[_displayLink setFrameInterval: 60 / _fps];
|
||||
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
-(void) stopMainLoop
|
||||
{
|
||||
if (_displayLink != nil)
|
||||
{
|
||||
[_displayLink invalidate];
|
||||
_displayLink = nil;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) setPreferredFPS:(int)fps
|
||||
{
|
||||
_fps = fps;
|
||||
[self startMainLoop];
|
||||
}
|
||||
|
||||
-(void) doCaller: (id) sender
|
||||
{
|
||||
static std::chrono::steady_clock::time_point prevTime;
|
||||
static std::chrono::steady_clock::time_point now;
|
||||
static float dt = 0.f;
|
||||
|
||||
if (_isAppActive)
|
||||
{
|
||||
EAGLContext* context = [(CCEAGLView*)(_application->getView()) getContext];
|
||||
if (context != [EAGLContext currentContext])
|
||||
{
|
||||
glFlush();
|
||||
}
|
||||
[EAGLContext setCurrentContext: context];
|
||||
|
||||
prevTime = std::chrono::steady_clock::now();
|
||||
|
||||
bool downsampleEnabled = _application->isDownsampleEnabled();
|
||||
if (downsampleEnabled)
|
||||
_application->getRenderTexture()->prepare();
|
||||
|
||||
_scheduler->update(dt);
|
||||
cocos2d::EventDispatcher::dispatchTickEvent(dt);
|
||||
|
||||
if (downsampleEnabled)
|
||||
_application->getRenderTexture()->draw();
|
||||
|
||||
[(CCEAGLView*)(_application->getView()) swapBuffers];
|
||||
cocos2d::PoolManager::getInstance()->getCurrentPool()->clear();
|
||||
|
||||
now = std::chrono::steady_clock::now();
|
||||
dt = std::chrono::duration_cast<std::chrono::microseconds>(now - prevTime).count() / 1000000.f;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
Application* Application::_instance = nullptr;
|
||||
std::shared_ptr<Scheduler> Application::_scheduler = nullptr;
|
||||
|
||||
Application::Application(const std::string& name, int width, int height)
|
||||
{
|
||||
Application::_instance = this;
|
||||
_scheduler = std::make_shared<Scheduler>();
|
||||
|
||||
createView(name, width, height);
|
||||
Configuration::getInstance();
|
||||
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_mainFBO);
|
||||
_renderTexture = new RenderTexture(width, height);
|
||||
|
||||
se::ScriptEngine::getInstance();
|
||||
EventDispatcher::init();
|
||||
|
||||
_delegate = [[MainLoop alloc] initWithApplication:this];
|
||||
|
||||
updateViewSize(width, height);
|
||||
}
|
||||
|
||||
Application::~Application()
|
||||
{
|
||||
|
||||
#if USE_AUDIO
|
||||
AudioEngine::end();
|
||||
#endif
|
||||
|
||||
EventDispatcher::destroy();
|
||||
se::ScriptEngine::destroyInstance();
|
||||
|
||||
// stop main loop
|
||||
[(MainLoop*)_delegate stopMainLoop];
|
||||
[(MainLoop*)_delegate release];
|
||||
_delegate = nullptr;
|
||||
|
||||
[(CCEAGLView*)_view release];
|
||||
_view = nullptr;
|
||||
|
||||
delete _renderTexture;
|
||||
_renderTexture = nullptr;
|
||||
|
||||
Application::_instance = nullptr;
|
||||
}
|
||||
|
||||
const cocos2d::Vec2& Application::getViewSize() const
|
||||
{
|
||||
return _viewSize;
|
||||
}
|
||||
|
||||
void Application::updateViewSize(int width, int height)
|
||||
{
|
||||
_viewSize.x = width;
|
||||
_viewSize.y = height;
|
||||
cocos2d::EventDispatcher::dispatchResizeEvent(width, height);
|
||||
}
|
||||
|
||||
void Application::start()
|
||||
{
|
||||
if (_delegate)
|
||||
// Replace performSelector usage for Apple review policy
|
||||
// https://github.com/cocos-creator/3d-tasks/issues/9770
|
||||
// [(MainLoop*)_delegate performSelector:@selector(firstStart:) withObject:(CCEAGLView*)_view afterDelay:0];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[(MainLoop*)_delegate firstStart:(CCEAGLView*)_view];
|
||||
});
|
||||
}
|
||||
|
||||
void Application::restart()
|
||||
{
|
||||
if (_delegate) {
|
||||
[(MainLoop*)_delegate stopMainLoop];
|
||||
// Replace performSelector usage for Apple review policy
|
||||
// https://github.com/cocos-creator/3d-tasks/issues/9770
|
||||
// [(MainLoop*)_delegate performSelector:@selector(firstStart:) withObject:(CCEAGLView*)_view afterDelay:0];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[(MainLoop*)_delegate firstStart:(CCEAGLView*)_view];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Application::end()
|
||||
{
|
||||
delete this;
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void Application::setPreferredFramesPerSecond(int fps)
|
||||
{
|
||||
[(MainLoop*)_delegate setPreferredFPS: fps];
|
||||
}
|
||||
|
||||
std::string Application::getCurrentLanguageCode() const
|
||||
{
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSArray *languages = [defaults objectForKey:@"AppleLanguages"];
|
||||
NSString *currentLanguage = [languages objectAtIndex:0];
|
||||
return [currentLanguage UTF8String];
|
||||
}
|
||||
|
||||
bool Application::isDisplayStats() {
|
||||
se::AutoHandleScope hs;
|
||||
se::Value ret;
|
||||
char commandBuf[100] = "cc.debug.isDisplayStats();";
|
||||
se::ScriptEngine::getInstance()->evalString(commandBuf, 100, &ret);
|
||||
return ret.toBoolean();
|
||||
}
|
||||
|
||||
void Application::setDisplayStats(bool isShow) {
|
||||
se::AutoHandleScope hs;
|
||||
char commandBuf[100] = {0};
|
||||
sprintf(commandBuf, "cc.debug.setDisplayStats(%s);", isShow ? "true" : "false");
|
||||
se::ScriptEngine::getInstance()->evalString(commandBuf);
|
||||
}
|
||||
|
||||
Application::LanguageType Application::getCurrentLanguage() const
|
||||
{
|
||||
// get the current language and country config
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSArray *languages = [defaults objectForKey:@"AppleLanguages"];
|
||||
NSString *currentLanguage = [languages objectAtIndex:0];
|
||||
|
||||
// get the current language code.(such as English is "en", Chinese is "zh" and so on)
|
||||
NSDictionary* temp = [NSLocale componentsFromLocaleIdentifier:currentLanguage];
|
||||
NSString * languageCode = [temp objectForKey:NSLocaleLanguageCode];
|
||||
|
||||
if ([languageCode isEqualToString:@"zh"]) return LanguageType::CHINESE;
|
||||
if ([languageCode isEqualToString:@"en"]) return LanguageType::ENGLISH;
|
||||
if ([languageCode isEqualToString:@"fr"]) return LanguageType::FRENCH;
|
||||
if ([languageCode isEqualToString:@"it"]) return LanguageType::ITALIAN;
|
||||
if ([languageCode isEqualToString:@"de"]) return LanguageType::GERMAN;
|
||||
if ([languageCode isEqualToString:@"es"]) return LanguageType::SPANISH;
|
||||
if ([languageCode isEqualToString:@"nl"]) return LanguageType::DUTCH;
|
||||
if ([languageCode isEqualToString:@"ru"]) return LanguageType::RUSSIAN;
|
||||
if ([languageCode isEqualToString:@"ko"]) return LanguageType::KOREAN;
|
||||
if ([languageCode isEqualToString:@"ja"]) return LanguageType::JAPANESE;
|
||||
if ([languageCode isEqualToString:@"hu"]) return LanguageType::HUNGARIAN;
|
||||
if ([languageCode isEqualToString:@"pt"]) return LanguageType::PORTUGUESE;
|
||||
if ([languageCode isEqualToString:@"ar"]) return LanguageType::ARABIC;
|
||||
if ([languageCode isEqualToString:@"nb"]) return LanguageType::NORWEGIAN;
|
||||
if ([languageCode isEqualToString:@"pl"]) return LanguageType::POLISH;
|
||||
if ([languageCode isEqualToString:@"tr"]) return LanguageType::TURKISH;
|
||||
if ([languageCode isEqualToString:@"uk"]) return LanguageType::UKRAINIAN;
|
||||
if ([languageCode isEqualToString:@"ro"]) return LanguageType::ROMANIAN;
|
||||
if ([languageCode isEqualToString:@"bg"]) return LanguageType::BULGARIAN;
|
||||
return LanguageType::ENGLISH;
|
||||
}
|
||||
|
||||
Application::Platform Application::getPlatform() const
|
||||
{
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) // idiom for iOS <= 3.2, otherwise: [UIDevice userInterfaceIdiom] is faster.
|
||||
return Platform::IPAD;
|
||||
else
|
||||
return Platform::IPHONE;
|
||||
}
|
||||
|
||||
float Application::getScreenScale() const
|
||||
{
|
||||
return [(UIView*)_view contentScaleFactor];
|
||||
}
|
||||
|
||||
GLint Application::getMainFBO() const
|
||||
{
|
||||
return _mainFBO;
|
||||
}
|
||||
|
||||
bool Application::openURL(const std::string &url)
|
||||
{
|
||||
NSString* msg = [NSString stringWithCString:url.c_str() encoding:NSUTF8StringEncoding];
|
||||
NSURL* nsUrl = [NSURL URLWithString:msg];
|
||||
return [[UIApplication sharedApplication] openURL:nsUrl];
|
||||
}
|
||||
|
||||
void Application::copyTextToClipboard(const std::string &text)
|
||||
{
|
||||
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
|
||||
pasteboard.string = [NSString stringWithCString:text.c_str() encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
bool Application::applicationDidFinishLaunching()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::onPause()
|
||||
{
|
||||
}
|
||||
|
||||
void Application::onResume()
|
||||
{
|
||||
}
|
||||
|
||||
void Application::setMultitouch(bool value)
|
||||
{
|
||||
if (value != _multiTouch)
|
||||
{
|
||||
_multiTouch = value;
|
||||
if (_view)
|
||||
[(CCEAGLView*)_view setMultipleTouchEnabled:_multiTouch];
|
||||
}
|
||||
}
|
||||
|
||||
void Application::onCreateView(PixelFormat& pixelformat, DepthFormat& depthFormat, int& multisamplingCount)
|
||||
{
|
||||
pixelformat = PixelFormat::RGB565;
|
||||
depthFormat = DepthFormat::DEPTH24_STENCIL8;
|
||||
|
||||
multisamplingCount = 0;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
GLenum depthFormatMap[] =
|
||||
{
|
||||
0, // NONE: no depth and no stencil
|
||||
GL_DEPTH_COMPONENT24_OES, // DEPTH_COMPONENT16: unsupport, convert to GL_DEPTH_COMPONENT24_OES
|
||||
GL_DEPTH_COMPONENT24_OES, // DEPTH_COMPONENT24
|
||||
GL_DEPTH_COMPONENT24_OES, // DEPTH_COMPONENT32F: unsupport, convert to GL_DEPTH_COMPONENT24_OES
|
||||
GL_DEPTH24_STENCIL8_OES, // DEPTH24_STENCIL8
|
||||
GL_DEPTH24_STENCIL8_OES, // DEPTH32F_STENCIL8: unsupport, convert to GL_DEPTH24_STENCIL8_OES
|
||||
GL_DEPTH_STENCIL_OES // STENCIL_INDEX8
|
||||
};
|
||||
|
||||
GLenum depthFormat2GLDepthFormat(cocos2d::Application::DepthFormat depthFormat)
|
||||
{
|
||||
return depthFormatMap[(int)depthFormat];
|
||||
}
|
||||
}
|
||||
|
||||
void Application::createView(const std::string& /*name*/, int width, int height)
|
||||
{
|
||||
PixelFormat pixelFormat = PixelFormat::RGB565;
|
||||
DepthFormat depthFormat = DepthFormat::DEPTH24_STENCIL8;
|
||||
int multisamplingCount = 0;
|
||||
|
||||
onCreateView(pixelFormat,
|
||||
depthFormat,
|
||||
multisamplingCount);
|
||||
|
||||
CGRect bounds;
|
||||
bounds.origin.x = 0;
|
||||
bounds.origin.y = 0;
|
||||
bounds.size.width = width;
|
||||
bounds.size.height = height;
|
||||
|
||||
//IDEA: iOS only support these pixel format?
|
||||
// - RGB565
|
||||
// - RGBA8
|
||||
NSString *pixelString = kEAGLColorFormatRGB565;
|
||||
if (PixelFormat::RGB565 != pixelFormat &&
|
||||
PixelFormat::RGBA8 != pixelFormat)
|
||||
NSLog(@"Unsupported pixel format is set, iOS only support RGB565 or RGBA8. Change to use RGB565");
|
||||
else if (PixelFormat::RGBA8 == pixelFormat)
|
||||
pixelString = kEAGLColorFormatRGBA8;
|
||||
|
||||
// create view
|
||||
CCEAGLView *eaglView = [CCEAGLView viewWithFrame: bounds
|
||||
pixelFormat: pixelString
|
||||
depthFormat: depthFormat2GLDepthFormat(depthFormat)
|
||||
preserveBackbuffer: NO
|
||||
sharegroup: nil
|
||||
multiSampling: multisamplingCount != 0
|
||||
numberOfSamples: multisamplingCount];
|
||||
|
||||
[eaglView setMultipleTouchEnabled:_multiTouch];
|
||||
|
||||
[eaglView retain];
|
||||
_view = eaglView;
|
||||
}
|
||||
|
||||
std::string Application::getSystemVersion()
|
||||
{
|
||||
NSString* systemVersion = [UIDevice currentDevice].systemVersion;
|
||||
return [systemVersion UTF8String];
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
317
cocos2d-x/cocos/platform/ios/CCDevice-ios.mm
Normal file
317
cocos2d-x/cocos/platform/ios/CCDevice-ios.mm
Normal file
@@ -0,0 +1,317 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "CCApplication.h"
|
||||
#include "platform/CCDevice.h"
|
||||
#include "platform/ios/CCEAGLView-ios.h"
|
||||
|
||||
// Vibrate
|
||||
#import <AudioToolbox/AudioToolbox.h>
|
||||
#include "base/ccTypes.h"
|
||||
#include "platform/apple/CCDevice-apple.h"
|
||||
#include "CCReachability.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
// Accelerometer
|
||||
#import <CoreMotion/CoreMotion.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreText/CoreText.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
static const float g = 9.80665;
|
||||
static const float radToDeg = (180/M_PI);
|
||||
|
||||
@interface CCMotionDispatcher : NSObject<UIAccelerometerDelegate>
|
||||
{
|
||||
CMMotionManager* _motionManager;
|
||||
cocos2d::Device::MotionValue _motionValue;
|
||||
float _interval; // unit: seconds
|
||||
bool _enabled;
|
||||
}
|
||||
|
||||
+ (id) sharedMotionDispatcher;
|
||||
- (id) init;
|
||||
- (void) setMotionEnabled: (bool) isEnabled;
|
||||
- (void) setMotionInterval:(float) interval;
|
||||
|
||||
@end
|
||||
|
||||
@implementation CCMotionDispatcher
|
||||
|
||||
static CCMotionDispatcher* __motionDispatcher = nullptr;
|
||||
|
||||
+ (id) sharedMotionDispatcher
|
||||
{
|
||||
if (__motionDispatcher == nil) {
|
||||
__motionDispatcher = [[CCMotionDispatcher alloc] init];
|
||||
}
|
||||
|
||||
return __motionDispatcher;
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if( (self = [super init]) ) {
|
||||
_enabled = false;
|
||||
_interval = 1.0f / 60.0f;
|
||||
_motionManager = [[CMMotionManager alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
__motionDispatcher = nullptr;
|
||||
[_motionManager release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) setMotionEnabled: (bool) enabled
|
||||
{
|
||||
if (_enabled == enabled)
|
||||
return;
|
||||
|
||||
bool isDeviceMotionAvailable = _motionManager.isDeviceMotionAvailable;
|
||||
if (enabled)
|
||||
{
|
||||
// Has Gyro? (iPhone4 and newer)
|
||||
if (isDeviceMotionAvailable) {
|
||||
[_motionManager startDeviceMotionUpdates];
|
||||
_motionManager.deviceMotionUpdateInterval = _interval;
|
||||
}
|
||||
// Only basic accelerometer data
|
||||
else {
|
||||
[_motionManager startAccelerometerUpdates];
|
||||
_motionManager.accelerometerUpdateInterval = _interval;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Has Gyro? (iPhone4 and newer)
|
||||
if (isDeviceMotionAvailable) {
|
||||
[_motionManager stopDeviceMotionUpdates];
|
||||
}
|
||||
// Only basic accelerometer data
|
||||
else {
|
||||
[_motionManager stopAccelerometerUpdates];
|
||||
}
|
||||
}
|
||||
_enabled = enabled;
|
||||
}
|
||||
|
||||
-(void) setMotionInterval:(float)interval
|
||||
{
|
||||
_interval = interval;
|
||||
if (_enabled)
|
||||
{
|
||||
if (_motionManager.isDeviceMotionAvailable) {
|
||||
_motionManager.deviceMotionUpdateInterval = _interval;
|
||||
}
|
||||
else {
|
||||
_motionManager.accelerometerUpdateInterval = _interval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(const cocos2d::Device::MotionValue&) getMotionValue {
|
||||
|
||||
if (_motionManager.isDeviceMotionAvailable) {
|
||||
CMDeviceMotion* motion = _motionManager.deviceMotion;
|
||||
_motionValue.accelerationX = motion.userAcceleration.x * g;
|
||||
_motionValue.accelerationY = motion.userAcceleration.y * g;
|
||||
_motionValue.accelerationZ = motion.userAcceleration.z * g;
|
||||
|
||||
_motionValue.accelerationIncludingGravityX = (motion.userAcceleration.x + motion.gravity.x) * g;
|
||||
_motionValue.accelerationIncludingGravityY = (motion.userAcceleration.y + motion.gravity.y) * g;
|
||||
_motionValue.accelerationIncludingGravityZ = (motion.userAcceleration.z + motion.gravity.z) * g;
|
||||
|
||||
_motionValue.rotationRateAlpha = motion.rotationRate.x * radToDeg;
|
||||
_motionValue.rotationRateBeta = motion.rotationRate.y * radToDeg;
|
||||
_motionValue.rotationRateGamma = motion.rotationRate.z * radToDeg;
|
||||
}
|
||||
else {
|
||||
CMAccelerometerData* acc = _motionManager.accelerometerData;
|
||||
_motionValue.accelerationIncludingGravityX = acc.acceleration.x * g;
|
||||
_motionValue.accelerationIncludingGravityY = acc.acceleration.y * g;
|
||||
_motionValue.accelerationIncludingGravityZ = acc.acceleration.z * g;
|
||||
}
|
||||
|
||||
return _motionValue;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
int Device::getDPI()
|
||||
{
|
||||
static int dpi = -1;
|
||||
|
||||
if (dpi == -1)
|
||||
{
|
||||
float scale = scale = [[UIScreen mainScreen] scale];
|
||||
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
dpi = 132 * scale;
|
||||
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
|
||||
dpi = 163 * scale;
|
||||
} else {
|
||||
dpi = 160 * scale;
|
||||
}
|
||||
}
|
||||
return dpi;
|
||||
}
|
||||
|
||||
|
||||
void Device::setAccelerometerEnabled(bool isEnabled)
|
||||
{
|
||||
#if !defined(CC_TARGET_OS_TVOS)
|
||||
[[CCMotionDispatcher sharedMotionDispatcher] setMotionEnabled:isEnabled];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Device::setAccelerometerInterval(float interval)
|
||||
{
|
||||
#if !defined(CC_TARGET_OS_TVOS)
|
||||
[[CCMotionDispatcher sharedMotionDispatcher] setMotionInterval:interval];
|
||||
#endif
|
||||
}
|
||||
|
||||
const Device::MotionValue& Device::getDeviceMotionValue()
|
||||
{
|
||||
#if !defined(CC_TARGET_OS_TVOS)
|
||||
return [[CCMotionDispatcher sharedMotionDispatcher] getMotionValue];
|
||||
#else
|
||||
static Device::MotionValue ret;
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
Device::Rotation Device::getDeviceRotation()
|
||||
{
|
||||
Rotation ret = Device::Rotation::_0;
|
||||
switch ([[UIApplication sharedApplication] statusBarOrientation])
|
||||
{
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
ret = Device::Rotation::_90;
|
||||
break;
|
||||
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
ret = Device::Rotation::_270;
|
||||
break;
|
||||
|
||||
case UIInterfaceOrientationPortraitUpsideDown:
|
||||
ret = Device::Rotation::_180;
|
||||
break;
|
||||
|
||||
case UIInterfaceOrientationPortrait:
|
||||
ret = Device::Rotation::_0;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string Device::getDeviceModel()
|
||||
{
|
||||
struct utsname systemInfo;
|
||||
uname(&systemInfo);
|
||||
return systemInfo.machine;
|
||||
}
|
||||
|
||||
void Device::setKeepScreenOn(bool value)
|
||||
{
|
||||
[[UIApplication sharedApplication] setIdleTimerDisabled:(BOOL)value];
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Only works on iOS devices that support vibration (such as iPhone). Should only be used for important alerts. Use risks rejection in iTunes Store.
|
||||
@param duration ignored for iOS
|
||||
*/
|
||||
void Device::vibrate(float duration)
|
||||
{
|
||||
// See https://developer.apple.com/library/ios/documentation/AudioToolbox/Reference/SystemSoundServicesReference/index.html#//apple_ref/c/econst/kSystemSoundID_Vibrate
|
||||
CC_UNUSED_PARAM(duration);
|
||||
|
||||
// automatically vibrates for approximately 0.4 seconds
|
||||
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
|
||||
}
|
||||
|
||||
float Device::getBatteryLevel()
|
||||
{
|
||||
return [UIDevice currentDevice].batteryLevel;
|
||||
}
|
||||
|
||||
Device::NetworkType Device::getNetworkType()
|
||||
{
|
||||
static Reachability* __reachability = nullptr;
|
||||
if (__reachability == nullptr)
|
||||
{
|
||||
__reachability = Reachability::createForInternetConnection();
|
||||
__reachability->retain();
|
||||
}
|
||||
|
||||
NetworkType ret = NetworkType::NONE;
|
||||
Reachability::NetworkStatus status = __reachability->getCurrentReachabilityStatus();
|
||||
switch (status) {
|
||||
case Reachability::NetworkStatus::REACHABLE_VIA_WIFI:
|
||||
ret = NetworkType::LAN;
|
||||
break;
|
||||
case Reachability::NetworkStatus::REACHABLE_VIA_WWAN:
|
||||
ret = NetworkType::WWAN;
|
||||
break;
|
||||
default:
|
||||
ret = NetworkType::NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
cocos2d::Vec4 Device::getSafeAreaEdge()
|
||||
{
|
||||
UIView* screenView = (UIView*)Application::getInstance()->getView();
|
||||
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
|
||||
float version = [[UIDevice currentDevice].systemVersion floatValue];
|
||||
if (version >= 11.0f)
|
||||
{
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wpartial-availability"
|
||||
UIEdgeInsets safeAreaEdge = screenView.safeAreaInsets;
|
||||
#pragma clang diagnostic pop
|
||||
return cocos2d::Vec4(safeAreaEdge.top, safeAreaEdge.left, safeAreaEdge.bottom, safeAreaEdge.right);
|
||||
}
|
||||
#endif
|
||||
|
||||
// If running on iOS devices lower than 11.0, return ZERO Vec4.
|
||||
return cocos2d::Vec4();
|
||||
}
|
||||
NS_CC_END
|
||||
121
cocos2d-x/cocos/platform/ios/CCEAGLView-ios.h
Normal file
121
cocos2d-x/cocos/platform/ios/CCEAGLView-ios.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
|
||||
===== IMPORTANT =====
|
||||
|
||||
This is sample code demonstrating API, technology or techniques in development.
|
||||
Although this sample code has been reviewed for technical accuracy, it is not
|
||||
final. Apple is supplying this information to help you plan for the adoption of
|
||||
the technologies and programming interfaces described herein. This information
|
||||
is subject to change, and software implemented based on this sample code should
|
||||
be tested with final operating system software and final documentation. Newer
|
||||
versions of this sample code may be provided with future seeds of the API or
|
||||
technology. For information about updates to this and other developer
|
||||
documentation, view the New & Updated sidebars in subsequent documentation
|
||||
seeds.
|
||||
|
||||
=====================
|
||||
|
||||
File: EAGLView.h
|
||||
Abstract: Convenience class that wraps the CAEAGLLayer from CoreAnimation into a
|
||||
UIView subclass.
|
||||
|
||||
Version: 1.3
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under
|
||||
Apple's copyrights in this original Apple software (the "Apple Software"), to
|
||||
use, reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions
|
||||
of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may be used
|
||||
to endorse or promote products derived from the Apple Software without specific
|
||||
prior written permission from Apple. Except as expressly stated in this notice,
|
||||
no other rights or licenses, express or implied, are granted by Apple herein,
|
||||
including but not limited to any patent rights that may be infringed by your
|
||||
derivative works or by other works in which the Apple Software may be
|
||||
incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
|
||||
DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
|
||||
CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
|
||||
APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2008 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <OpenGLES/EAGL.h>
|
||||
#import <OpenGLES/EAGLDrawable.h>
|
||||
#import <OpenGLES/ES2/gl.h>
|
||||
#import <OpenGLES/ES2/glext.h>
|
||||
#import <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
//CLASS INTERFACE:
|
||||
|
||||
/** CCEAGLView Class.
|
||||
* This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass.
|
||||
* The view content is basically an EAGL surface you render your OpenGL scene into.
|
||||
* Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel.
|
||||
*/
|
||||
@interface CCEAGLView : UIView
|
||||
{
|
||||
@private
|
||||
EAGLContext *_context;
|
||||
GLuint _defaultFramebuffer;
|
||||
GLuint _defaultColorBuffer;
|
||||
GLuint _defaultDepthBuffer;
|
||||
|
||||
//fsaa addition
|
||||
BOOL _multisampling;
|
||||
int _requestedSamples;
|
||||
GLuint _msaaFramebuffer;
|
||||
GLuint _msaaColorBuffer;
|
||||
GLuint _msaaDepthBuffer;
|
||||
|
||||
NSString *_pixelformatString;
|
||||
GLenum _pixelformat;
|
||||
GLuint _depthFormat;
|
||||
BOOL _preserveBackbuffer;
|
||||
BOOL _discardFramebufferSupported;
|
||||
EAGLSharegroup* _sharegroup;
|
||||
|
||||
unsigned int _touchIds;
|
||||
UITouch* _touches[10];
|
||||
BOOL _isReady;
|
||||
|
||||
BOOL _needToPreventTouch;
|
||||
}
|
||||
|
||||
/** creates an initializes an CCEAGLView with a frame, a color buffer format, a depth buffer format, a sharegroup, and multisampling */
|
||||
+(id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)multisampling numberOfSamples:(unsigned int)samples;
|
||||
|
||||
/** Initializes an CCEAGLView with a frame, a color buffer format, a depth buffer format, a sharegroup and multisampling support */
|
||||
-(id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)sampling numberOfSamples:(unsigned int)nSamples;
|
||||
|
||||
/** CCEAGLView uses double-buffer. This method swaps the buffers */
|
||||
-(void) swapBuffers;
|
||||
|
||||
-(BOOL) isReady;
|
||||
-(void) setPreventTouchEvent:(BOOL) flag;
|
||||
-(EAGLContext*) getContext;
|
||||
@end
|
||||
577
cocos2d-x/cocos/platform/ios/CCEAGLView-ios.mm
Normal file
577
cocos2d-x/cocos/platform/ios/CCEAGLView-ios.mm
Normal file
@@ -0,0 +1,577 @@
|
||||
/*
|
||||
|
||||
===== IMPORTANT =====
|
||||
|
||||
This is sample code demonstrating API, technology or techniques in development.
|
||||
Although this sample code has been reviewed for technical accuracy, it is not
|
||||
final. Apple is supplying this information to help you plan for the adoption of
|
||||
the technologies and programming interfaces described herein. This information
|
||||
is subject to change, and software implemented based on this sample code should
|
||||
be tested with final operating system software and final documentation. Newer
|
||||
versions of this sample code may be provided with future seeds of the API or
|
||||
technology. For information about updates to this and other developer
|
||||
documentation, view the New & Updated sidebars in subsequent documentation
|
||||
seeds.
|
||||
|
||||
=====================
|
||||
|
||||
File: EAGLView.m
|
||||
Abstract: Convenience class that wraps the CAEAGLLayer from CoreAnimation into a
|
||||
UIView subclass.
|
||||
|
||||
Version: 1.3
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under
|
||||
Apple's copyrights in this original Apple software (the "Apple Software"), to
|
||||
use, reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions
|
||||
of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may be used
|
||||
to endorse or promote products derived from the Apple Software without specific
|
||||
prior written permission from Apple. Except as expressly stated in this notice,
|
||||
no other rights or licenses, express or implied, are granted by Apple herein,
|
||||
including but not limited to any patent rights that may be infringed by your
|
||||
derivative works or by other works in which the Apple Software may be
|
||||
incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
|
||||
DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
|
||||
CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
|
||||
APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2008 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
|
||||
#import "platform/ios/CCEAGLView-ios.h"
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
#include "scripting/js-bindings/event/EventDispatcher.h"
|
||||
#include "platform/ios/OpenGL_Internal-ios.h"
|
||||
#include "platform/CCApplication.h"
|
||||
#include "base/ccMacros.h"
|
||||
#include "ui/edit-box/EditBox.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
GLenum pixelformat2glenum(NSString* str)
|
||||
{
|
||||
if ([str isEqualToString:kEAGLColorFormatRGB565])
|
||||
return GL_RGB565;
|
||||
else
|
||||
return GL_RGBA8_OES;
|
||||
}
|
||||
}
|
||||
|
||||
//CLASS IMPLEMENTATIONS:
|
||||
|
||||
#define MAX_TOUCH_COUNT 10
|
||||
|
||||
@interface CCEAGLView (Private)
|
||||
@end
|
||||
|
||||
@implementation CCEAGLView
|
||||
|
||||
+ (Class) layerClass
|
||||
{
|
||||
return [CAEAGLLayer class];
|
||||
}
|
||||
|
||||
+ (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)multisampling numberOfSamples:(unsigned int)samples
|
||||
{
|
||||
return [[[self alloc]initWithFrame:frame pixelFormat:format depthFormat:depth preserveBackbuffer:retained sharegroup:sharegroup multiSampling:multisampling numberOfSamples:samples] autorelease];
|
||||
}
|
||||
|
||||
- (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)sampling numberOfSamples:(unsigned int)nSamples;
|
||||
{
|
||||
if((self = [super initWithFrame:frame]))
|
||||
{
|
||||
_pixelformatString = format;
|
||||
_pixelformat = pixelformat2glenum(_pixelformatString);
|
||||
_depthFormat = depth;
|
||||
// Multisampling doc: https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/WorkingwithEAGLContexts/WorkingwithEAGLContexts.html#//apple_ref/doc/uid/TP40008793-CH103-SW4
|
||||
_multisampling = sampling;
|
||||
_requestedSamples = nSamples;
|
||||
_preserveBackbuffer = retained;
|
||||
_sharegroup = sharegroup;
|
||||
_isReady = FALSE;
|
||||
_needToPreventTouch = FALSE;
|
||||
|
||||
#if GL_EXT_discard_framebuffer == 1
|
||||
_discardFramebufferSupported = YES;
|
||||
#else
|
||||
_discardFramebufferSupported = NO;
|
||||
#endif
|
||||
self.contentScaleFactor = [[UIScreen mainScreen] scale];
|
||||
|
||||
_touchIds = 0;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
_touches[i] = nil;
|
||||
|
||||
[self setupGLContext];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (_defaultColorBuffer)
|
||||
{
|
||||
glDeleteRenderbuffers(1, &_defaultColorBuffer);
|
||||
_defaultColorBuffer = 0;
|
||||
}
|
||||
|
||||
if (_defaultDepthBuffer)
|
||||
{
|
||||
glDeleteRenderbuffers(1, &_defaultDepthBuffer);
|
||||
_defaultDepthBuffer = 0;
|
||||
}
|
||||
|
||||
if (_defaultFramebuffer)
|
||||
{
|
||||
glDeleteFramebuffers(1, &_defaultFramebuffer);
|
||||
_defaultFramebuffer = 0;
|
||||
}
|
||||
|
||||
if (_msaaColorBuffer)
|
||||
{
|
||||
glDeleteRenderbuffers(1, &_msaaColorBuffer);
|
||||
_msaaColorBuffer = 0;
|
||||
}
|
||||
|
||||
if (_msaaDepthBuffer)
|
||||
{
|
||||
glDeleteRenderbuffers(1, &_msaaDepthBuffer);
|
||||
_msaaDepthBuffer = 0;
|
||||
}
|
||||
|
||||
if (_msaaFramebuffer)
|
||||
{
|
||||
glDeleteFramebuffers(1, &_msaaFramebuffer);
|
||||
_msaaFramebuffer = 0;
|
||||
}
|
||||
|
||||
if ([EAGLContext currentContext] == _context)
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
|
||||
if (_context)
|
||||
{
|
||||
[_context release];
|
||||
_context = nil;
|
||||
}
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) layoutSubviews
|
||||
{
|
||||
// On some devices with iOS13, `[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer]`
|
||||
// will return false if lock screen when running application, which make framebuffer in invalid state.
|
||||
// FIXME: do binding framebuffer in other place?
|
||||
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
|
||||
if (state == UIApplicationStateBackground)
|
||||
return;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _defaultFramebuffer);
|
||||
if (_defaultColorBuffer)
|
||||
{
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _defaultColorBuffer);
|
||||
if(! [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer])
|
||||
{
|
||||
NSLog(@"failed to call context");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int backingWidth = 0;
|
||||
int backingHeight = 0;
|
||||
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
|
||||
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
|
||||
|
||||
if (_defaultDepthBuffer)
|
||||
{
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _defaultDepthBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, _depthFormat, backingWidth, backingHeight);
|
||||
}
|
||||
|
||||
if (_multisampling)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _msaaFramebuffer);
|
||||
if (_msaaColorBuffer)
|
||||
{
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _msaaColorBuffer);
|
||||
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, _requestedSamples, _pixelformat, backingWidth, backingHeight);
|
||||
}
|
||||
|
||||
if (_msaaDepthBuffer)
|
||||
{
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _msaaDepthBuffer);
|
||||
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, _requestedSamples, _depthFormat, backingWidth, backingHeight);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _defaultColorBuffer);
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
GLenum error;
|
||||
if( (error=glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE)
|
||||
NSLog(@"Failed to make complete framebuffer object 0x%X", error);
|
||||
|
||||
_isReady = TRUE;
|
||||
}
|
||||
|
||||
- (BOOL) isReady
|
||||
{
|
||||
return _isReady;
|
||||
}
|
||||
|
||||
-(void) setPreventTouchEvent:(BOOL) flag
|
||||
{
|
||||
_needToPreventTouch = flag;
|
||||
}
|
||||
|
||||
-(EAGLContext*) getContext
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
- (void) setupGLContext
|
||||
{
|
||||
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
|
||||
|
||||
eaglLayer.opaque = YES;
|
||||
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithBool:_preserveBackbuffer], kEAGLDrawablePropertyRetainedBacking,
|
||||
_pixelformatString, kEAGLDrawablePropertyColorFormat, nil];
|
||||
|
||||
if(! _sharegroup)
|
||||
{
|
||||
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
|
||||
if (!_context)
|
||||
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
}
|
||||
else
|
||||
{
|
||||
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3 sharegroup:_sharegroup];
|
||||
if (!_context)
|
||||
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:_sharegroup];
|
||||
}
|
||||
|
||||
if (!_context || ![EAGLContext setCurrentContext:_context] )
|
||||
{
|
||||
NSLog(@"Can not crate GL context.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (![self createFrameBuffer])
|
||||
return;
|
||||
if (![self createAndAttachColorBuffer])
|
||||
return;
|
||||
|
||||
[self createAndAttachDepthBuffer];
|
||||
}
|
||||
|
||||
- (BOOL) createFrameBuffer
|
||||
{
|
||||
if (!_context)
|
||||
return FALSE;
|
||||
|
||||
glGenFramebuffers(1, &_defaultFramebuffer);
|
||||
if (0 == _defaultFramebuffer)
|
||||
{
|
||||
NSLog(@"Can not create default frame buffer.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (_multisampling)
|
||||
{
|
||||
glGenFramebuffers(1, &_msaaFramebuffer);
|
||||
if (0 == _msaaFramebuffer)
|
||||
{
|
||||
NSLog(@"Can not create multi sampling frame buffer");
|
||||
_multisampling = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (BOOL) createAndAttachColorBuffer
|
||||
{
|
||||
if (0 == _defaultFramebuffer)
|
||||
return FALSE;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _defaultFramebuffer);
|
||||
glGenRenderbuffers(1, &_defaultColorBuffer);
|
||||
if (0 == _defaultColorBuffer)
|
||||
{
|
||||
NSLog(@"Can not create default color buffer.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _defaultColorBuffer);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _defaultColorBuffer);
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
if (!_multisampling || (0 == _msaaFramebuffer))
|
||||
return TRUE;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _msaaFramebuffer);
|
||||
glGenRenderbuffers(1, &_msaaColorBuffer);
|
||||
if (0 == _msaaColorBuffer)
|
||||
{
|
||||
NSLog(@"Can not create multi sampling color buffer.");
|
||||
|
||||
// App can work without multi sampleing.
|
||||
return TRUE;
|
||||
}
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _msaaColorBuffer);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _msaaColorBuffer);
|
||||
CHECK_GL_ERROR();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (BOOL) createAndAttachDepthBuffer
|
||||
{
|
||||
if (0 == _defaultFramebuffer || 0 == _depthFormat)
|
||||
return FALSE;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _defaultFramebuffer);
|
||||
glGenRenderbuffers(1, &_defaultDepthBuffer);
|
||||
if (0 == _defaultDepthBuffer)
|
||||
{
|
||||
NSLog(@"Can not create default depth buffer.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _defaultDepthBuffer);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _defaultDepthBuffer);
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
if (GL_DEPTH24_STENCIL8_OES == _depthFormat ||
|
||||
GL_DEPTH_STENCIL_OES == _depthFormat)
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _defaultDepthBuffer);
|
||||
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
if (!_multisampling || (0 == _msaaFramebuffer))
|
||||
return TRUE;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _msaaFramebuffer);
|
||||
glGenRenderbuffers(1, &_msaaDepthBuffer);
|
||||
if (0 == _msaaDepthBuffer)
|
||||
{
|
||||
NSLog(@"Can not create multi sampling depth buffer.");
|
||||
return TRUE;
|
||||
}
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _msaaDepthBuffer);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _msaaDepthBuffer);
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
if (GL_DEPTH24_STENCIL8_OES == _depthFormat ||
|
||||
GL_DEPTH_STENCIL_OES == _depthFormat)
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _msaaDepthBuffer);
|
||||
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (void) swapBuffers
|
||||
{
|
||||
// IMPORTANT:
|
||||
// - preconditions
|
||||
// -> context_ MUST be the OpenGL context
|
||||
// -> renderbuffer_ must be the RENDER BUFFER
|
||||
|
||||
if (_multisampling)
|
||||
{
|
||||
/* Resolve from msaaFramebuffer to resolveFramebuffer */
|
||||
//glDisable(GL_SCISSOR_TEST);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER_APPLE, _msaaFramebuffer);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_APPLE, _defaultFramebuffer);
|
||||
glResolveMultisampleFramebufferAPPLE();
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
if (_discardFramebufferSupported)
|
||||
{
|
||||
if (_multisampling)
|
||||
{
|
||||
if (_depthFormat)
|
||||
{
|
||||
GLenum attachments[] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT};
|
||||
glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 2, attachments);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLenum attachments[] = {GL_COLOR_ATTACHMENT0};
|
||||
glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 1, attachments);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (_depthFormat)
|
||||
{
|
||||
// not MSAA
|
||||
GLenum attachments[] = { GL_DEPTH_ATTACHMENT};
|
||||
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _defaultColorBuffer);
|
||||
|
||||
if(![_context presentRenderbuffer:GL_RENDERBUFFER])
|
||||
NSLog(@"cocos2d: Failed to swap renderbuffer in %s\n", __FUNCTION__);
|
||||
|
||||
#if COCOS2D_DEBUG
|
||||
CHECK_GL_ERROR();
|
||||
#endif
|
||||
|
||||
// We can safely re-bind the framebuffer here, since this will be the
|
||||
// 1st instruction of the new main loop
|
||||
if(_multisampling)
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _msaaFramebuffer);
|
||||
}
|
||||
|
||||
// Pass the touches to the superview
|
||||
#pragma mark CCEAGLView - Touch Delegate
|
||||
|
||||
namespace
|
||||
{
|
||||
int getUnusedID(unsigned int& touchIDs)
|
||||
{
|
||||
int i;
|
||||
unsigned int temp = touchIDs;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (! (temp & 0x00000001))
|
||||
{
|
||||
touchIDs |= (1 << i);
|
||||
return i;
|
||||
}
|
||||
|
||||
temp >>= 1;
|
||||
}
|
||||
|
||||
// all bits are used
|
||||
return -1;
|
||||
}
|
||||
|
||||
void resetTouchID(unsigned int& touchIDs, int index)
|
||||
{
|
||||
touchIDs &= ((1 << index) ^ 0xffffffff);
|
||||
}
|
||||
|
||||
cocos2d::TouchInfo createTouchInfo(int index, UITouch* touch, float contentScaleFactor)
|
||||
{
|
||||
uint8_t deviceRatio = cocos2d::Application::getInstance()->getDevicePixelRatio();
|
||||
// TouchInfo should located in UI coordinate system, not GL pixels
|
||||
// It will be converted to display position later in View.convertToLocationInView
|
||||
cocos2d::TouchInfo touchInfo;
|
||||
touchInfo.index = index;
|
||||
touchInfo.x = [touch locationInView: [touch view]].x / deviceRatio;
|
||||
touchInfo.y = [touch locationInView: [touch view]].y / deviceRatio;
|
||||
return touchInfo;
|
||||
}
|
||||
|
||||
void deliverTouch(cocos2d::TouchEvent& touchEvent,
|
||||
NSSet* touches,
|
||||
UITouch** internalTouches,
|
||||
float contentScaleFactor,
|
||||
bool reset,
|
||||
unsigned int& touchIds)
|
||||
{
|
||||
for (UITouch *touch in touches)
|
||||
{
|
||||
for (int i = 0; i < MAX_TOUCH_COUNT; ++i)
|
||||
{
|
||||
if (touch == internalTouches[i])
|
||||
{
|
||||
if (reset)
|
||||
{
|
||||
internalTouches[i] = nil;
|
||||
resetTouchID(touchIds, i);
|
||||
}
|
||||
touchEvent.touches.push_back(createTouchInfo(i, touch, contentScaleFactor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!touchEvent.touches.empty())
|
||||
cocos2d::EventDispatcher::dispatchTouchEvent(touchEvent);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
// When editbox is editing, should prevent glview to handle touch events.
|
||||
if (_needToPreventTouch)
|
||||
{
|
||||
cocos2d::EditBox::complete();
|
||||
return;
|
||||
}
|
||||
|
||||
cocos2d::TouchEvent touchEvent;
|
||||
touchEvent.type = cocos2d::TouchEvent::Type::BEGAN;
|
||||
for (UITouch *touch in touches) {
|
||||
int index = getUnusedID(_touchIds);
|
||||
if (-1 == index)
|
||||
return;
|
||||
|
||||
_touches[index] = touch;
|
||||
|
||||
touchEvent.touches.push_back(createTouchInfo(index, touch, self.contentScaleFactor));
|
||||
}
|
||||
|
||||
if (!touchEvent.touches.empty())
|
||||
cocos2d::EventDispatcher::dispatchTouchEvent(touchEvent);
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
cocos2d::TouchEvent touchEvent;
|
||||
touchEvent.type = cocos2d::TouchEvent::Type::MOVED;
|
||||
deliverTouch(touchEvent, touches, _touches, self.contentScaleFactor, false, _touchIds);
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
cocos2d::TouchEvent touchEvent;
|
||||
touchEvent.type = cocos2d::TouchEvent::Type::ENDED;
|
||||
deliverTouch(touchEvent, touches, _touches, self.contentScaleFactor, true, _touchIds);
|
||||
}
|
||||
|
||||
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
cocos2d::TouchEvent touchEvent;
|
||||
touchEvent.type = cocos2d::TouchEvent::Type::CANCELLED;
|
||||
deliverTouch(touchEvent, touches, _touches, self.contentScaleFactor, true, _touchIds);
|
||||
}
|
||||
|
||||
@end
|
||||
49
cocos2d-x/cocos/platform/ios/CCGL-ios.h
Normal file
49
cocos2d-x/cocos/platform/ios/CCGL-ios.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
|
||||
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
#include <OpenGLES/ES2/glext.h>
|
||||
|
||||
#define glClearDepth glClearDepthf
|
||||
#define glDepthRange glDepthRangef
|
||||
//#define glDeleteVertexArrays glDeleteVertexArraysOES
|
||||
#define glGenVertexArrays glGenVertexArraysOES
|
||||
#define glBindVertexArray glBindVertexArrayOES
|
||||
//#define glMapBuffer glMapBufferOES
|
||||
//#define glUnmapBuffer glUnmapBufferOES
|
||||
//
|
||||
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
|
||||
//#define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES
|
||||
//#define GL_WRITE_ONLY GL_WRITE_ONLY_OES
|
||||
|
||||
//#define GL_MAX_SAMPLES_APPLE GL_MAX_SAMPLES
|
||||
|
||||
#endif // CC_PLATFORM_IOS
|
||||
127
cocos2d-x/cocos/platform/ios/CCImage-ios.mm
Normal file
127
cocos2d-x/cocos/platform/ios/CCImage-ios.mm
Normal file
@@ -0,0 +1,127 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
|
||||
|
||||
#import "platform/CCImage.h"
|
||||
#import <string>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
bool cocos2d::Image::saveToFile(const std::string& filename, bool isToRGB)
|
||||
{
|
||||
bool saveToPNG = false;
|
||||
bool needToCopyPixels = false;
|
||||
|
||||
std::string basename(filename);
|
||||
std::transform(basename.begin(), basename.end(), basename.begin(), ::tolower);
|
||||
if (std::string::npos != basename.find(".png"))
|
||||
{
|
||||
saveToPNG = true;
|
||||
}
|
||||
|
||||
int bitsPerComponent = 8;
|
||||
int bitsPerPixel = hasAlpha() ? 32 : 24;
|
||||
if ((! saveToPNG) || isToRGB)
|
||||
{
|
||||
bitsPerPixel = 24;
|
||||
}
|
||||
|
||||
int bytesPerRow = (bitsPerPixel/8) * _width;
|
||||
int myDataLength = bytesPerRow * _height;
|
||||
|
||||
unsigned char *pixels = _data;
|
||||
|
||||
// The data has alpha channel, and want to save it with an RGB png file,
|
||||
// or want to save as jpg, remove the alpha channel.
|
||||
if (hasAlpha() && bitsPerPixel == 24)
|
||||
{
|
||||
pixels = new (std::nothrow) unsigned char[myDataLength];
|
||||
|
||||
for (int i = 0; i < _height; ++i)
|
||||
{
|
||||
for (int j = 0; j < _width; ++j)
|
||||
{
|
||||
pixels[(i * _width + j) * 3] = _data[(i * _width + j) * 4];
|
||||
pixels[(i * _width + j) * 3 + 1] = _data[(i * _width + j) * 4 + 1];
|
||||
pixels[(i * _width + j) * 3 + 2] = _data[(i * _width + j) * 4 + 2];
|
||||
}
|
||||
}
|
||||
|
||||
needToCopyPixels = true;
|
||||
}
|
||||
|
||||
// make data provider with data.
|
||||
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
|
||||
if (saveToPNG && hasAlpha() && (! isToRGB))
|
||||
{
|
||||
bitmapInfo |= kCGImageAlphaPremultipliedLast;
|
||||
}
|
||||
CGDataProviderRef provider = CGDataProviderCreateWithData(nullptr, pixels, myDataLength, nullptr);
|
||||
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
|
||||
CGImageRef iref = CGImageCreate(_width, _height,
|
||||
bitsPerComponent, bitsPerPixel, bytesPerRow,
|
||||
colorSpaceRef, bitmapInfo, provider,
|
||||
nullptr, false,
|
||||
kCGRenderingIntentDefault);
|
||||
|
||||
UIImage* image = [[UIImage alloc] initWithCGImage:iref];
|
||||
|
||||
CGImageRelease(iref);
|
||||
CGColorSpaceRelease(colorSpaceRef);
|
||||
CGDataProviderRelease(provider);
|
||||
|
||||
// NOTE: Prevent memory leak. Requires ARC enabled.
|
||||
@autoreleasepool {
|
||||
NSData *data;
|
||||
if (saveToPNG) {
|
||||
data = UIImagePNGRepresentation(image);
|
||||
} else {
|
||||
data = UIImageJPEGRepresentation(image, 1.0f);
|
||||
}
|
||||
[data writeToFile:[NSString stringWithUTF8String:filename.c_str()] atomically:YES];
|
||||
}
|
||||
|
||||
[image release];
|
||||
|
||||
if (needToCopyPixels)
|
||||
{
|
||||
delete [] pixels;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // CC_PLATFORM_IOS
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
// Module setting for engine
|
||||
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) USE_SOCKET=1 USE_DRAGONBONES=1 USE_SPINE=1 USE_AUDIO=1 USE_EDIT_BOX=1 USE_WEB_VIEW=1 USE_VIDEO=1
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
// Module setting for engine
|
||||
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) USE_SOCKET=1 USE_DRAGONBONES=1 USE_SPINE=1 USE_AUDIO=1 USE_EDIT_BOX=1 USE_WEB_VIEW=1 USE_VIDEO=1
|
||||
|
||||
54
cocos2d-x/cocos/platform/ios/CCPlatformDefine-ios.h
Normal file
54
cocos2d-x/cocos/platform/ios/CCPlatformDefine-ios.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#ifndef __CCPLATFORMDEFINE_H__
|
||||
#define __CCPLATFORMDEFINE_H__
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define CC_DLL
|
||||
|
||||
#define CC_ASSERT(cond) assert(cond)
|
||||
|
||||
|
||||
#define CC_UNUSED_PARAM(unusedparam) (void)unusedparam
|
||||
|
||||
/* Define NULL pointer value */
|
||||
#ifndef NULL
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif // CC_PLATFORM_IOS
|
||||
|
||||
#endif /* __CCPLATFORMDEFINE_H__*/
|
||||
|
||||
246
cocos2d-x/cocos/platform/ios/CCReachability.cpp
Normal file
246
cocos2d-x/cocos/platform/ios/CCReachability.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "CCReachability.h"
|
||||
#include "base/ccMacros.h"
|
||||
|
||||
#include <SystemConfiguration/SystemConfiguration.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
namespace {
|
||||
|
||||
#define ShouldPrintReachabilityFlags 0
|
||||
|
||||
static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment)
|
||||
{
|
||||
#if ShouldPrintReachabilityFlags
|
||||
|
||||
printf("Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
|
||||
(flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
|
||||
#else
|
||||
'-',
|
||||
#endif
|
||||
(flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
|
||||
|
||||
(flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
|
||||
(flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
|
||||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
|
||||
(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
|
||||
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
|
||||
(flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
|
||||
(flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-',
|
||||
comment
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
cocos2d::Reachability::NetworkStatus getNetworkStatusForFlags(SCNetworkReachabilityFlags flags)
|
||||
{
|
||||
PrintReachabilityFlags(flags, "networkStatusForFlags");
|
||||
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
|
||||
{
|
||||
// The target host is not reachable.
|
||||
return cocos2d::Reachability::NetworkStatus::NOT_REACHABLE;
|
||||
}
|
||||
|
||||
cocos2d::Reachability::NetworkStatus returnValue = cocos2d::Reachability::NetworkStatus::NOT_REACHABLE;
|
||||
|
||||
if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
|
||||
{
|
||||
/*
|
||||
If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi...
|
||||
*/
|
||||
returnValue = cocos2d::Reachability::NetworkStatus::REACHABLE_VIA_WIFI;
|
||||
}
|
||||
|
||||
if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
|
||||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
|
||||
{
|
||||
/*
|
||||
... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs...
|
||||
*/
|
||||
|
||||
if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
|
||||
{
|
||||
/*
|
||||
... and no [user] intervention is needed...
|
||||
*/
|
||||
returnValue = cocos2d::Reachability::NetworkStatus::REACHABLE_VIA_WIFI;
|
||||
}
|
||||
}
|
||||
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
|
||||
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
|
||||
{
|
||||
/*
|
||||
... but WWAN connections are OK if the calling application is using the CFNetwork APIs.
|
||||
*/
|
||||
returnValue = cocos2d::Reachability::NetworkStatus::REACHABLE_VIA_WWAN;
|
||||
}
|
||||
#endif
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
Reachability* Reachability::createWithHostName(const std::string& hostName)
|
||||
{
|
||||
Reachability* returnValue = nullptr;
|
||||
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(nullptr, hostName.c_str());
|
||||
if (reachability != nullptr)
|
||||
{
|
||||
returnValue = new (std::nothrow) Reachability();
|
||||
if (returnValue != nullptr)
|
||||
{
|
||||
returnValue->autorelease();
|
||||
returnValue->_reachabilityRef = reachability;
|
||||
}
|
||||
else {
|
||||
CFRelease(reachability);
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
Reachability* Reachability::createWithAddress(const struct sockaddr* hostAddress)
|
||||
{
|
||||
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, hostAddress);
|
||||
|
||||
Reachability* returnValue = nullptr;
|
||||
|
||||
if (reachability != nullptr)
|
||||
{
|
||||
returnValue = new (std::nothrow) Reachability();
|
||||
if (returnValue != nullptr)
|
||||
{
|
||||
returnValue->autorelease();
|
||||
returnValue->_reachabilityRef = reachability;
|
||||
}
|
||||
else {
|
||||
CFRelease(reachability);
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
Reachability* Reachability::createForInternetConnection()
|
||||
{
|
||||
struct sockaddr_in zeroAddress;
|
||||
bzero(&zeroAddress, sizeof(zeroAddress));
|
||||
zeroAddress.sin_len = sizeof(zeroAddress);
|
||||
zeroAddress.sin_family = AF_INET;
|
||||
|
||||
return createWithAddress((const struct sockaddr*) &zeroAddress);
|
||||
}
|
||||
|
||||
Reachability::Reachability()
|
||||
: _callback(nullptr)
|
||||
, _userData(nullptr)
|
||||
, _reachabilityRef(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Reachability::~Reachability()
|
||||
{
|
||||
stopNotifier();
|
||||
if (_reachabilityRef != nullptr)
|
||||
{
|
||||
CFRelease(_reachabilityRef);
|
||||
}
|
||||
}
|
||||
|
||||
void Reachability::onReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
|
||||
{
|
||||
CCASSERT(info != nullptr, "info was nullptr in onReachabilityCallback");
|
||||
|
||||
cocos2d::Reachability* thiz = reinterpret_cast<cocos2d::Reachability*>(info);
|
||||
if (thiz->_callback != nullptr)
|
||||
{
|
||||
NetworkStatus status = getNetworkStatusForFlags(flags);
|
||||
thiz->_callback(thiz, status, thiz->_userData);
|
||||
}
|
||||
}
|
||||
|
||||
bool Reachability::startNotifier(const ReachabilityCallback& cb, void* userData)
|
||||
{
|
||||
_callback = cb;
|
||||
_userData = userData;
|
||||
|
||||
bool returnValue = false;
|
||||
SCNetworkReachabilityContext context = {0, this, nullptr, nullptr, nullptr};
|
||||
|
||||
if (SCNetworkReachabilitySetCallback(_reachabilityRef, onReachabilityCallback, &context))
|
||||
{
|
||||
if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
|
||||
{
|
||||
returnValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void Reachability::stopNotifier()
|
||||
{
|
||||
if (_reachabilityRef != nullptr)
|
||||
{
|
||||
SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||
}
|
||||
}
|
||||
|
||||
bool Reachability::isConnectionRequired() const
|
||||
{
|
||||
CCASSERT(_reachabilityRef != nullptr, "connectionRequired called with nullptr reachabilityRef");
|
||||
SCNetworkReachabilityFlags flags;
|
||||
|
||||
if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
|
||||
{
|
||||
return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Reachability::NetworkStatus Reachability::getCurrentReachabilityStatus() const
|
||||
{
|
||||
CCASSERT(_reachabilityRef != nullptr, "currentNetworkStatus called with nullptr SCNetworkReachabilityRef");
|
||||
NetworkStatus returnValue = NetworkStatus::NOT_REACHABLE;
|
||||
SCNetworkReachabilityFlags flags;
|
||||
|
||||
if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
|
||||
{
|
||||
returnValue = getNetworkStatusForFlags(flags);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
89
cocos2d-x/cocos/platform/ios/CCReachability.h
Normal file
89
cocos2d-x/cocos/platform/ios/CCReachability.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "base/CCRef.h"
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <SystemConfiguration/SystemConfiguration.h>
|
||||
|
||||
struct sockaddr;
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
class Reachability final : public Ref
|
||||
{
|
||||
public:
|
||||
enum class NetworkStatus : uint8_t
|
||||
{
|
||||
NOT_REACHABLE,
|
||||
REACHABLE_VIA_WIFI,
|
||||
REACHABLE_VIA_WWAN
|
||||
};
|
||||
|
||||
/*!
|
||||
* Use to check the reachability of a given host name.
|
||||
*/
|
||||
static Reachability* createWithHostName(const std::string& hostName);
|
||||
|
||||
/*!
|
||||
* Use to check the reachability of a given IP address.
|
||||
*/
|
||||
static Reachability* createWithAddress(const struct sockaddr* hostAddress);
|
||||
|
||||
/*!
|
||||
* Checks whether the default route is available. Should be used by applications that do not connect to a particular host.
|
||||
*/
|
||||
static Reachability* createForInternetConnection();
|
||||
|
||||
using ReachabilityCallback = std::function<void(Reachability*, NetworkStatus, void*)>;
|
||||
|
||||
/*!
|
||||
* Start listening for reachability notifications on the current run loop.
|
||||
*/
|
||||
bool startNotifier(const ReachabilityCallback& cb, void* userData);
|
||||
void stopNotifier();
|
||||
|
||||
NetworkStatus getCurrentReachabilityStatus()const;
|
||||
|
||||
/*!
|
||||
* WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand.
|
||||
*/
|
||||
bool isConnectionRequired() const;
|
||||
|
||||
private:
|
||||
|
||||
Reachability();
|
||||
~Reachability();
|
||||
|
||||
static void onReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info);
|
||||
|
||||
ReachabilityCallback _callback;
|
||||
void* _userData;
|
||||
SCNetworkReachabilityRef _reachabilityRef;
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
||||
89
cocos2d-x/cocos/platform/ios/OpenGL_Internal-ios.h
Normal file
89
cocos2d-x/cocos/platform/ios/OpenGL_Internal-ios.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
|
||||
===== IMPORTANT =====
|
||||
|
||||
This is sample code demonstrating API, technology or techniques in development.
|
||||
Although this sample code has been reviewed for technical accuracy, it is not
|
||||
final. Apple is supplying this information to help you plan for the adoption of
|
||||
the technologies and programming interfaces described herein. This information
|
||||
is subject to change, and software implemented based on this sample code should
|
||||
be tested with final operating system software and final documentation. Newer
|
||||
versions of this sample code may be provided with future seeds of the API or
|
||||
technology. For information about updates to this and other developer
|
||||
documentation, view the New & Updated sidebars in subsequent documentation
|
||||
seeds.
|
||||
|
||||
=====================
|
||||
|
||||
File: OpenGL_Internal.h
|
||||
Abstract: This file is included for support purposes and isn't necessary for
|
||||
understanding this sample.
|
||||
|
||||
Version: 1.0
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under
|
||||
Apple's copyrights in this original Apple software (the "Apple Software"), to
|
||||
use, reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions
|
||||
of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may be used
|
||||
to endorse or promote products derived from the Apple Software without specific
|
||||
prior written permission from Apple. Except as expressly stated in this notice,
|
||||
no other rights or licenses, express or implied, are granted by Apple herein,
|
||||
including but not limited to any patent rights that may be infringed by your
|
||||
derivative works or by other works in which the Apple Software may be
|
||||
incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
|
||||
DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
|
||||
CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
|
||||
APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2008 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
|
||||
|
||||
/* Generic error reporting */
|
||||
#define REPORT_ERROR(__FORMAT__, ...) printf("%s: %s\n", __FUNCTION__, [[NSString stringWithFormat:__FORMAT__, __VA_ARGS__] UTF8String])
|
||||
|
||||
/* EAGL and GL functions calling wrappers that log on error */
|
||||
#define CALL_EAGL_FUNCTION(__FUNC__, ...) ({ EAGLError __error = __FUNC__( __VA_ARGS__ ); if(__error != kEAGLErrorSuccess) printf("%s() called from %s returned error %i\n", #__FUNC__, __FUNCTION__, __error); (__error ? NO : YES); })
|
||||
//#define CHECK_GL_ERROR() ({ GLenum __error = glGetError(); if(__error) printf("OpenGL error 0x%04X in %s\n", __error, __FUNCTION__); (__error ? NO : YES); })
|
||||
#define CHECK_GL_ERROR() ({ GLenum __error = glGetError(); if(__error) printf("OpenGL error 0x%04X in %s %d\n", __error, __FUNCTION__, __LINE__); })
|
||||
|
||||
|
||||
/* Optional delegate methods support */
|
||||
#ifndef __DELEGATE_IVAR__
|
||||
#define __DELEGATE_IVAR__ _delegate
|
||||
#endif
|
||||
#ifndef __DELEGATE_METHODS_IVAR__
|
||||
#define __DELEGATE_METHODS_IVAR__ _delegateMethods
|
||||
#endif
|
||||
#define TEST_DELEGATE_METHOD_BIT(__BIT__) (self->__DELEGATE_METHODS_IVAR__ & (1 << __BIT__))
|
||||
/* Comment out for Apple review policy */
|
||||
// https://github.com/cocos-creator/3d-tasks/issues/9770
|
||||
// #define SET_DELEGATE_METHOD_BIT(__BIT__, __NAME__) { if([self->__DELEGATE_IVAR__ respondsToSelector:@selector(__NAME__)]) self->__DELEGATE_METHODS_IVAR__ |= (1 << __BIT__); else self->__DELEGATE_METHODS_IVAR__ &= ~(1 << __BIT__); }
|
||||
|
||||
#endif // CC_PLATFORM_IOS
|
||||
|
||||
39
cocos2d-x/cocos/platform/ios/cocos2d-prefix.pch
Normal file
39
cocos2d-x/cocos/platform/ios/cocos2d-prefix.pch
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Prefix header for all source files of the 'cocos2dx' target in the 'cocos2dx' project
|
||||
//
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
#include <OpenGLES/ES2/glext.h>
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <stack>
|
||||
#endif
|
||||
334
cocos2d-x/cocos/platform/mac/CCApplication-mac.mm
Normal file
334
cocos2d-x/cocos/platform/mac/CCApplication-mac.mm
Normal file
@@ -0,0 +1,334 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "platform/CCApplication.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include "base/CCScheduler.h"
|
||||
#include "base/CCAutoreleasePool.h"
|
||||
#include "base/CCGLUtils.h"
|
||||
#include "base/CCConfiguration.h"
|
||||
#include "platform/desktop/CCGLView-desktop.h"
|
||||
#include "scripting/js-bindings/event/EventDispatcher.h"
|
||||
#include "scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "base/CCGLUtils.h"
|
||||
#include "audio/include/AudioEngine.h"
|
||||
#include "cocos/renderer/gfx/DeviceGraphics.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
namespace
|
||||
{
|
||||
bool setCanvasCallback(se::Object* global)
|
||||
{
|
||||
auto viewSize = Application::getInstance()->getViewSize();
|
||||
se::ScriptEngine* se = se::ScriptEngine::getInstance();
|
||||
char commandBuf[200] = {0};
|
||||
int devicePixelRatio = Application::getInstance()->getScreenScale();
|
||||
//set window.innerWidth/innerHeight in CSS pixel units, not physical pixel units.
|
||||
sprintf(commandBuf, "window.innerWidth = %d; window.innerHeight = %d;",
|
||||
(int)(viewSize.x / devicePixelRatio),
|
||||
(int)(viewSize.y / devicePixelRatio));
|
||||
se->evalString(commandBuf);
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Application* Application::_instance = nullptr;
|
||||
std::shared_ptr<Scheduler> Application::_scheduler = nullptr;
|
||||
|
||||
#define CAST_VIEW(view) ((GLView*)view)
|
||||
|
||||
Application::Application(const std::string& name, int width, int height)
|
||||
{
|
||||
Application::_instance = this;
|
||||
|
||||
createView(name, width, height);
|
||||
|
||||
Configuration::getInstance();
|
||||
|
||||
_renderTexture = new RenderTexture(width, height);
|
||||
_scheduler = std::make_shared<Scheduler>();
|
||||
|
||||
EventDispatcher::init();
|
||||
se::ScriptEngine::getInstance();
|
||||
}
|
||||
|
||||
Application::~Application()
|
||||
{
|
||||
|
||||
#if USE_AUDIO
|
||||
AudioEngine::end();
|
||||
#endif
|
||||
|
||||
EventDispatcher::destroy();
|
||||
se::ScriptEngine::destroyInstance();
|
||||
|
||||
delete CAST_VIEW(_view);
|
||||
_view = nullptr;
|
||||
|
||||
delete _renderTexture;
|
||||
_renderTexture = nullptr;
|
||||
|
||||
Application::_instance = nullptr;
|
||||
}
|
||||
|
||||
const cocos2d::Vec2& Application::getViewSize() const
|
||||
{
|
||||
return _viewSize;
|
||||
}
|
||||
|
||||
void Application::updateViewSize(int width, int height)
|
||||
{
|
||||
_viewSize.x = width;
|
||||
_viewSize.y = height;
|
||||
}
|
||||
|
||||
void Application::start()
|
||||
{
|
||||
if (!_view)
|
||||
return;
|
||||
|
||||
float dt = 0.f;
|
||||
long long actualInternal = 0; // actual frame internal
|
||||
long long desiredInterval = 0; // desired frame internal, 1 / fps
|
||||
|
||||
std::chrono::steady_clock::time_point prev;
|
||||
std::chrono::steady_clock::time_point now;
|
||||
|
||||
prev = std::chrono::steady_clock::now();
|
||||
|
||||
se::ScriptEngine* se = se::ScriptEngine::getInstance();
|
||||
|
||||
while (!CAST_VIEW(_view)->windowShouldClose())
|
||||
{
|
||||
desiredInterval = 1.0 / _fps * 1000000;
|
||||
if (!_isStarted)
|
||||
{
|
||||
auto scheduler = Application::getInstance()->getScheduler();
|
||||
scheduler->removeAllFunctionsToBePerformedInCocosThread();
|
||||
scheduler->unscheduleAll();
|
||||
|
||||
se::ScriptEngine::getInstance()->cleanup();
|
||||
cocos2d::PoolManager::getInstance()->getCurrentPool()->clear();
|
||||
cocos2d::EventDispatcher::init();
|
||||
|
||||
ccInvalidateStateCache();
|
||||
se->addRegisterCallback(setCanvasCallback);
|
||||
|
||||
if(!applicationDidFinishLaunching())
|
||||
return;
|
||||
|
||||
_isStarted = true;
|
||||
}
|
||||
|
||||
// should be invoked at the begin of rendering a frame
|
||||
if (_isDownsampleEnabled)
|
||||
_renderTexture->prepare();
|
||||
|
||||
CAST_VIEW(_view)->pollEvents();
|
||||
|
||||
if (_isStarted)
|
||||
{
|
||||
now = std::chrono::steady_clock::now();
|
||||
actualInternal = std::chrono::duration_cast<std::chrono::microseconds>(now - prev).count();
|
||||
if (actualInternal >= desiredInterval)
|
||||
{
|
||||
prev = now;
|
||||
dt = (float)actualInternal / 1000000.f;
|
||||
_scheduler->update(dt);
|
||||
|
||||
EventDispatcher::dispatchTickEvent(dt);
|
||||
|
||||
if (_isDownsampleEnabled)
|
||||
_renderTexture->draw();
|
||||
|
||||
CAST_VIEW(_view)->swapBuffers();
|
||||
PoolManager::getInstance()->getCurrentPool()->clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// sleep 3ms may make a sleep of 4ms
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(desiredInterval - actualInternal - 1000));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(desiredInterval));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::restart()
|
||||
{
|
||||
_isStarted = false;
|
||||
}
|
||||
|
||||
void Application::end()
|
||||
{
|
||||
glfwSetWindowShouldClose(CAST_VIEW(_view)->getGLFWWindow(), 1);
|
||||
}
|
||||
|
||||
void Application::setPreferredFramesPerSecond(int fps)
|
||||
{
|
||||
_fps = fps;
|
||||
}
|
||||
|
||||
Application::Platform Application::getPlatform() const
|
||||
{
|
||||
return Platform::MAC;
|
||||
}
|
||||
|
||||
std::string Application::getCurrentLanguageCode() const
|
||||
{
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSArray *languages = [defaults objectForKey:@"AppleLanguages"];
|
||||
NSString *currentLanguage = [languages objectAtIndex:0];
|
||||
return [currentLanguage UTF8String];
|
||||
}
|
||||
|
||||
bool Application::isDisplayStats() {
|
||||
se::AutoHandleScope hs;
|
||||
se::Value ret;
|
||||
char commandBuf[100] = "cc.debug.isDisplayStats();";
|
||||
se::ScriptEngine::getInstance()->evalString(commandBuf, 100, &ret);
|
||||
return ret.toBoolean();
|
||||
}
|
||||
|
||||
void Application::setDisplayStats(bool isShow) {
|
||||
se::AutoHandleScope hs;
|
||||
char commandBuf[100] = {0};
|
||||
sprintf(commandBuf, "cc.debug.setDisplayStats(%s);", isShow ? "true" : "false");
|
||||
se::ScriptEngine::getInstance()->evalString(commandBuf);
|
||||
}
|
||||
|
||||
Application::LanguageType Application::getCurrentLanguage() const
|
||||
{
|
||||
// get the current language and country config
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSArray *languages = [defaults objectForKey:@"AppleLanguages"];
|
||||
NSString *currentLanguage = [languages objectAtIndex:0];
|
||||
|
||||
// get the current language code.(such as English is "en", Chinese is "zh" and so on)
|
||||
NSDictionary* temp = [NSLocale componentsFromLocaleIdentifier:currentLanguage];
|
||||
NSString * languageCode = [temp objectForKey:NSLocaleLanguageCode];
|
||||
|
||||
if ([languageCode isEqualToString:@"zh"]) return LanguageType::CHINESE;
|
||||
if ([languageCode isEqualToString:@"en"]) return LanguageType::ENGLISH;
|
||||
if ([languageCode isEqualToString:@"fr"]) return LanguageType::FRENCH;
|
||||
if ([languageCode isEqualToString:@"it"]) return LanguageType::ITALIAN;
|
||||
if ([languageCode isEqualToString:@"de"]) return LanguageType::GERMAN;
|
||||
if ([languageCode isEqualToString:@"es"]) return LanguageType::SPANISH;
|
||||
if ([languageCode isEqualToString:@"nl"]) return LanguageType::DUTCH;
|
||||
if ([languageCode isEqualToString:@"ru"]) return LanguageType::RUSSIAN;
|
||||
if ([languageCode isEqualToString:@"ko"]) return LanguageType::KOREAN;
|
||||
if ([languageCode isEqualToString:@"ja"]) return LanguageType::JAPANESE;
|
||||
if ([languageCode isEqualToString:@"hu"]) return LanguageType::HUNGARIAN;
|
||||
if ([languageCode isEqualToString:@"pt"]) return LanguageType::PORTUGUESE;
|
||||
if ([languageCode isEqualToString:@"ar"]) return LanguageType::ARABIC;
|
||||
if ([languageCode isEqualToString:@"nb"]) return LanguageType::NORWEGIAN;
|
||||
if ([languageCode isEqualToString:@"pl"]) return LanguageType::POLISH;
|
||||
if ([languageCode isEqualToString:@"tr"]) return LanguageType::TURKISH;
|
||||
if ([languageCode isEqualToString:@"uk"]) return LanguageType::UKRAINIAN;
|
||||
if ([languageCode isEqualToString:@"ro"]) return LanguageType::ROMANIAN;
|
||||
if ([languageCode isEqualToString:@"bg"]) return LanguageType::BULGARIAN;
|
||||
return LanguageType::ENGLISH;
|
||||
}
|
||||
|
||||
float Application::getScreenScale() const
|
||||
{
|
||||
return CAST_VIEW(_view)->getScale();
|
||||
}
|
||||
|
||||
GLint Application::getMainFBO() const
|
||||
{
|
||||
return CAST_VIEW(_view)->getMainFBO();
|
||||
}
|
||||
|
||||
bool Application::openURL(const std::string &url)
|
||||
{
|
||||
NSString* msg = [NSString stringWithCString:url.c_str() encoding:NSUTF8StringEncoding];
|
||||
NSURL* nsUrl = [NSURL URLWithString:msg];
|
||||
return [[NSWorkspace sharedWorkspace] openURL:nsUrl];
|
||||
}
|
||||
|
||||
void Application::copyTextToClipboard(const std::string &text)
|
||||
{
|
||||
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
|
||||
[pasteboard clearContents];
|
||||
NSString* tmp = [NSString stringWithCString:text.c_str() encoding:NSUTF8StringEncoding];
|
||||
[pasteboard setString:tmp forType:NSStringPboardType];
|
||||
}
|
||||
|
||||
bool Application::applicationDidFinishLaunching()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::onPause()
|
||||
{
|
||||
}
|
||||
|
||||
void Application::onResume()
|
||||
{
|
||||
}
|
||||
|
||||
void Application::setMultitouch(bool)
|
||||
{
|
||||
}
|
||||
|
||||
void Application::onCreateView(PixelFormat& pixelformat, DepthFormat& depthFormat, int& multisamplingCount)
|
||||
{
|
||||
pixelformat = PixelFormat::RGBA8;
|
||||
depthFormat = DepthFormat::DEPTH24_STENCIL8;
|
||||
|
||||
multisamplingCount = 0;
|
||||
}
|
||||
|
||||
void Application::createView(const std::string& name, int width, int height)
|
||||
{
|
||||
int multisamplingCount = 0;
|
||||
PixelFormat pixelformat;
|
||||
DepthFormat depthFormat;
|
||||
|
||||
onCreateView(pixelformat,
|
||||
depthFormat,
|
||||
multisamplingCount);
|
||||
|
||||
_view = new GLView(this, name, 0, 0, width, height, pixelformat, depthFormat, multisamplingCount);
|
||||
}
|
||||
|
||||
std::string Application::getSystemVersion()
|
||||
{
|
||||
NSOperatingSystemVersion v = NSProcessInfo.processInfo.operatingSystemVersion;
|
||||
char version[50] = {0};
|
||||
snprintf(version, sizeof(version), "%d.%d.%d", (int)v.majorVersion, (int)v.minorVersion, (int)v.patchVersion);
|
||||
return version;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
128
cocos2d-x/cocos/platform/mac/CCDevice-mac.mm
Normal file
128
cocos2d-x/cocos/platform/mac/CCDevice-mac.mm
Normal file
@@ -0,0 +1,128 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
|
||||
#include "platform/CCDevice.h"
|
||||
#include "platform/apple/CCDevice-apple.h"
|
||||
#include "base/ccTypes.h"
|
||||
#include "CCReachability.h"
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <string>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
int Device::getDPI()
|
||||
{
|
||||
NSScreen *screen = [NSScreen mainScreen];
|
||||
NSDictionary *description = [screen deviceDescription];
|
||||
NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue];
|
||||
CGSize displayPhysicalSize = CGDisplayScreenSize([[description objectForKey:@"NSScreenNumber"] unsignedIntValue]);
|
||||
|
||||
return ((displayPixelSize.width / displayPhysicalSize.width) * 25.4f);
|
||||
}
|
||||
|
||||
void Device::setAccelerometerEnabled(bool isEnabled)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Device::setAccelerometerInterval(float interval)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const Device::MotionValue& Device::getDeviceMotionValue()
|
||||
{
|
||||
static MotionValue __motionValue;
|
||||
return __motionValue;
|
||||
}
|
||||
|
||||
Device::Rotation Device::getDeviceRotation()
|
||||
{
|
||||
return Device::Rotation::_0;
|
||||
}
|
||||
|
||||
std::string Device::getDeviceModel()
|
||||
{
|
||||
struct utsname systemInfo;
|
||||
uname(&systemInfo);
|
||||
return systemInfo.machine;
|
||||
}
|
||||
|
||||
void Device::setKeepScreenOn(bool value)
|
||||
{
|
||||
CC_UNUSED_PARAM(value);
|
||||
}
|
||||
|
||||
void Device::vibrate(float duration)
|
||||
{
|
||||
CC_UNUSED_PARAM(duration);
|
||||
}
|
||||
|
||||
float Device::getBatteryLevel()
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
Device::NetworkType Device::getNetworkType()
|
||||
{
|
||||
static Reachability* __reachability = nullptr;
|
||||
if (__reachability == nullptr)
|
||||
{
|
||||
__reachability = Reachability::createForInternetConnection();
|
||||
__reachability->retain();
|
||||
}
|
||||
|
||||
NetworkType ret = NetworkType::NONE;
|
||||
Reachability::NetworkStatus status = __reachability->getCurrentReachabilityStatus();
|
||||
switch (status) {
|
||||
case Reachability::NetworkStatus::REACHABLE_VIA_WIFI:
|
||||
ret = NetworkType::LAN;
|
||||
break;
|
||||
case Reachability::NetworkStatus::REACHABLE_VIA_WWAN:
|
||||
ret = NetworkType::WWAN;
|
||||
default:
|
||||
ret = NetworkType::NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
cocos2d::Vec4 Device::getSafeAreaEdge()
|
||||
{
|
||||
// no SafeArea concept on mac, return ZERO Vec4.
|
||||
return cocos2d::Vec4();
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
51
cocos2d-x/cocos/platform/mac/CCGL-mac.h
Normal file
51
cocos2d-x/cocos/platform/mac/CCGL-mac.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __PLATFORM_MAC_CCGL_H__
|
||||
#define __PLATFORM_MAC_CCGL_H__
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
|
||||
#import <OpenGL/gl.h>
|
||||
#import <OpenGL/glu.h>
|
||||
#import <OpenGL/glext.h>
|
||||
|
||||
#define CC_GL_DEPTH24_STENCIL8 -1
|
||||
|
||||
|
||||
#define glDeleteVertexArrays glDeleteVertexArraysAPPLE
|
||||
#define glGenVertexArrays glGenVertexArraysAPPLE
|
||||
#define glBindVertexArray glBindVertexArrayAPPLE
|
||||
#define glClearDepthf glClearDepth
|
||||
#define glDepthRangef glDepthRange
|
||||
#define glReleaseShaderCompiler(xxx)
|
||||
|
||||
|
||||
#endif // __PLATFORM_MAC_CCGL_H__
|
||||
|
||||
#endif //s CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
// Module setting for engine
|
||||
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) USE_SOCKET=1 USE_DRAGONBONES=1 USE_SPINE=1 USE_AUDIO=1 USE_EDIT_BOX=1 USE_WEB_VIEW=1 USE_VIDEO=1
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
// Module setting for engine
|
||||
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) USE_SOCKET=1 USE_DRAGONBONES=1 USE_SPINE=1 USE_AUDIO=1 USE_EDIT_BOX=1 USE_WEB_VIEW=1 USE_VIDEO=1
|
||||
|
||||
61
cocos2d-x/cocos/platform/mac/CCPlatformDefine-mac.h
Normal file
61
cocos2d-x/cocos/platform/mac/CCPlatformDefine-mac.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __CCPLATFORMDEFINE_H__
|
||||
#define __CCPLATFORMDEFINE_H__
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _USRDLL
|
||||
#define CC_DLL __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#define CC_DLL
|
||||
#endif
|
||||
|
||||
#if CC_DISABLE_ASSERT > 0
|
||||
#define CC_ASSERT(cond)
|
||||
#else
|
||||
#define CC_ASSERT(cond) assert(cond)
|
||||
#endif
|
||||
|
||||
#define CC_UNUSED_PARAM(unusedparam) (void)unusedparam
|
||||
|
||||
/* Define NULL pointer value */
|
||||
#ifndef NULL
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
|
||||
#endif /* __CCPLATFORMDEFINE_H__*/
|
||||
|
||||
39
cocos2d-x/cocos/platform/mac/cocos2d-prefix.pch
Normal file
39
cocos2d-x/cocos/platform/mac/cocos2d-prefix.pch
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Prefix header for all source files of the 'cocos2dx' target in the 'cocos2dx' project
|
||||
//
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
#import <OpenGL/gl.h>
|
||||
#import <OpenGL/glu.h>
|
||||
#import <OpenGL/glext.h>
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <stack>
|
||||
#endif
|
||||
435
cocos2d-x/cocos/platform/win32/CCApplication-win32.cpp
Normal file
435
cocos2d-x/cocos/platform/win32/CCApplication-win32.cpp
Normal file
@@ -0,0 +1,435 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "platform/CCApplication.h"
|
||||
#include "platform/CCStdC.h" // need it to include Windows.h
|
||||
#include <algorithm>
|
||||
#include <shellapi.h>
|
||||
#include <MMSystem.h>
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include "platform/desktop/CCGLView-desktop.h"
|
||||
#include "renderer/gfx/DeviceGraphics.h"
|
||||
#include "scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "scripting/js-bindings/event/EventDispatcher.h"
|
||||
#include "base/CCScheduler.h"
|
||||
#include "base/CCAutoreleasePool.h"
|
||||
#include "base/CCGLUtils.h"
|
||||
#include "audio/include/AudioEngine.h"
|
||||
|
||||
#define CAST_VIEW(view) ((GLView*)view)
|
||||
|
||||
namespace
|
||||
{
|
||||
/**
|
||||
@brief This function changes the PVRFrame show/hide setting in register.
|
||||
@param bEnable If true show the PVRFrame window, otherwise hide.
|
||||
*/
|
||||
void PVRFrameEnableControlWindow(bool bEnable)
|
||||
{
|
||||
HKEY hKey = 0;
|
||||
|
||||
// Open PVRFrame control key, if not exist create it.
|
||||
if(ERROR_SUCCESS != RegCreateKeyExW(HKEY_CURRENT_USER,
|
||||
L"Software\\Imagination Technologies\\PVRVFRame\\STARTUP\\",
|
||||
0,
|
||||
0,
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
KEY_ALL_ACCESS,
|
||||
0,
|
||||
&hKey,
|
||||
nullptr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const WCHAR* wszValue = L"hide_gui";
|
||||
const WCHAR* wszNewData = (bEnable) ? L"NO" : L"YES";
|
||||
WCHAR wszOldData[256] = {0};
|
||||
DWORD dwSize = sizeof(wszOldData);
|
||||
LSTATUS status = RegQueryValueExW(hKey, wszValue, 0, nullptr, (LPBYTE)wszOldData, &dwSize);
|
||||
if (ERROR_FILE_NOT_FOUND == status // the key not exist
|
||||
|| (ERROR_SUCCESS == status // or the hide_gui value is exist
|
||||
&& 0 != wcscmp(wszNewData, wszOldData))) // but new data and old data not equal
|
||||
{
|
||||
dwSize = sizeof(WCHAR) * (wcslen(wszNewData) + 1);
|
||||
RegSetValueEx(hKey, wszValue, 0, REG_SZ, (const BYTE *)wszNewData, dwSize);
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
bool setCanvasCallback(se::Object* global)
|
||||
{
|
||||
auto viewSize = cocos2d::Application::getInstance()->getViewSize();
|
||||
se::ScriptEngine* se = se::ScriptEngine::getInstance();
|
||||
uint8_t devicePixelRatio = cocos2d::Application::getInstance()->getScreenScale();
|
||||
char commandBuf[200] = {0};
|
||||
sprintf(commandBuf, "window.innerWidth = %d; window.innerHeight = %d;",
|
||||
(int)(viewSize.x / devicePixelRatio),
|
||||
(int)(viewSize.y / devicePixelRatio));
|
||||
se->evalString(commandBuf);
|
||||
cocos2d::ccViewport(0, 0, viewSize.x, viewSize.y);
|
||||
glDepthMask(GL_TRUE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
Application* Application::_instance = nullptr;
|
||||
std::shared_ptr<Scheduler> Application::_scheduler = nullptr;
|
||||
|
||||
Application::Application(const std::string& name, int width, int height)
|
||||
{
|
||||
Application::_instance = this;
|
||||
_scheduler = std::make_shared<Scheduler>();
|
||||
|
||||
createView(name, width, height);
|
||||
|
||||
_renderTexture = new RenderTexture(width, height);
|
||||
|
||||
EventDispatcher::init();
|
||||
se::ScriptEngine::getInstance();
|
||||
}
|
||||
|
||||
Application::~Application()
|
||||
{
|
||||
|
||||
#if USE_AUDIO
|
||||
AudioEngine::end();
|
||||
#endif
|
||||
|
||||
EventDispatcher::destroy();
|
||||
se::ScriptEngine::destroyInstance();
|
||||
|
||||
delete CAST_VIEW(_view);
|
||||
_view = nullptr;
|
||||
|
||||
delete _renderTexture;
|
||||
_renderTexture = nullptr;
|
||||
|
||||
Application::_instance = nullptr;
|
||||
}
|
||||
|
||||
const cocos2d::Vec2& Application::getViewSize() const
|
||||
{
|
||||
return _viewSize;
|
||||
}
|
||||
|
||||
void Application::updateViewSize(int width, int height)
|
||||
{
|
||||
_viewSize.x = width;
|
||||
_viewSize.y = height;
|
||||
}
|
||||
|
||||
void Application::start()
|
||||
{
|
||||
if (!_view)
|
||||
return;
|
||||
|
||||
PVRFrameEnableControlWindow(false);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/////////////// changing timer resolution
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
UINT TARGET_RESOLUTION = 1; // 1 millisecond target resolution
|
||||
TIMECAPS tc;
|
||||
UINT wTimerRes = 0;
|
||||
if (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(TIMECAPS)))
|
||||
{
|
||||
wTimerRes = std::min(std::max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
|
||||
timeBeginPeriod(wTimerRes);
|
||||
}
|
||||
|
||||
float dt = 0.f;
|
||||
const DWORD _16ms = 16;
|
||||
|
||||
// Main message loop:
|
||||
LARGE_INTEGER nFreq;
|
||||
LARGE_INTEGER nLast;
|
||||
LARGE_INTEGER nNow;
|
||||
|
||||
LONGLONG actualInterval = 0LL; // actual frame internal
|
||||
LONGLONG desiredInterval = 0LL; // desired frame internal, 1 / fps
|
||||
LONG waitMS = 0L;
|
||||
|
||||
QueryPerformanceCounter(&nLast);
|
||||
QueryPerformanceFrequency(&nFreq);
|
||||
se::ScriptEngine* se = se::ScriptEngine::getInstance();
|
||||
while (!CAST_VIEW(_view)->windowShouldClose())
|
||||
{
|
||||
desiredInterval = (LONGLONG)(1.0 / _fps * nFreq.QuadPart);
|
||||
if (!_isStarted)
|
||||
{
|
||||
auto scheduler = Application::getInstance()->getScheduler();
|
||||
scheduler->removeAllFunctionsToBePerformedInCocosThread();
|
||||
scheduler->unscheduleAll();
|
||||
|
||||
se::ScriptEngine::getInstance()->cleanup();
|
||||
cocos2d::PoolManager::getInstance()->getCurrentPool()->clear();
|
||||
cocos2d::EventDispatcher::init();
|
||||
|
||||
ccInvalidateStateCache();
|
||||
se->addRegisterCallback(setCanvasCallback);
|
||||
|
||||
if(!applicationDidFinishLaunching())
|
||||
return;
|
||||
|
||||
_isStarted = true;
|
||||
}
|
||||
|
||||
// should be invoked at the begin of rendering a frame
|
||||
if (_isDownsampleEnabled)
|
||||
_renderTexture->prepare();
|
||||
CAST_VIEW(_view)->pollEvents();
|
||||
if(_isStarted)
|
||||
{
|
||||
QueryPerformanceCounter(&nNow);
|
||||
actualInterval = nNow.QuadPart - nLast.QuadPart;
|
||||
if (actualInterval >= desiredInterval)
|
||||
{
|
||||
nLast.QuadPart = nNow.QuadPart;
|
||||
dt = (float)actualInterval / nFreq.QuadPart;
|
||||
_scheduler->update(dt);
|
||||
|
||||
EventDispatcher::dispatchTickEvent(dt);
|
||||
|
||||
if (_isDownsampleEnabled)
|
||||
_renderTexture->draw();
|
||||
|
||||
CAST_VIEW(_view)->swapBuffers();
|
||||
PoolManager::getInstance()->getCurrentPool()->clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// The precision of timer on Windows is set to highest (1ms) by 'timeBeginPeriod' from above code,
|
||||
// but it's still not precise enough. For example, if the precision of timer is 1ms,
|
||||
// Sleep(3) may make a sleep of 2ms or 4ms. Therefore, we subtract 1ms here to make Sleep time shorter.
|
||||
// If 'waitMS' is equal or less than 1ms, don't sleep and run into next loop to
|
||||
// boost CPU to next frame accurately.
|
||||
waitMS = (desiredInterval - actualInterval) * 1000LL / nFreq.QuadPart - 1L;
|
||||
if (waitMS > 1L)
|
||||
Sleep(waitMS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Sleep(_16ms);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (wTimerRes != 0)
|
||||
timeEndPeriod(wTimerRes);
|
||||
}
|
||||
|
||||
void Application::restart()
|
||||
{
|
||||
_isStarted = false;
|
||||
}
|
||||
|
||||
void Application::end()
|
||||
{
|
||||
glfwSetWindowShouldClose(CAST_VIEW(_view)->getGLFWWindow(), 1);
|
||||
}
|
||||
|
||||
void Application::setPreferredFramesPerSecond(int fps)
|
||||
{
|
||||
_fps = fps;
|
||||
}
|
||||
|
||||
Application::LanguageType Application::getCurrentLanguage() const
|
||||
{
|
||||
LanguageType ret = LanguageType::ENGLISH;
|
||||
|
||||
LCID localeID = GetUserDefaultLCID();
|
||||
unsigned short primaryLanguageID = localeID & 0xFF;
|
||||
|
||||
switch (primaryLanguageID)
|
||||
{
|
||||
case LANG_CHINESE:
|
||||
ret = LanguageType::CHINESE;
|
||||
break;
|
||||
case LANG_ENGLISH:
|
||||
ret = LanguageType::ENGLISH;
|
||||
break;
|
||||
case LANG_FRENCH:
|
||||
ret = LanguageType::FRENCH;
|
||||
break;
|
||||
case LANG_ITALIAN:
|
||||
ret = LanguageType::ITALIAN;
|
||||
break;
|
||||
case LANG_GERMAN:
|
||||
ret = LanguageType::GERMAN;
|
||||
break;
|
||||
case LANG_SPANISH:
|
||||
ret = LanguageType::SPANISH;
|
||||
break;
|
||||
case LANG_DUTCH:
|
||||
ret = LanguageType::DUTCH;
|
||||
break;
|
||||
case LANG_RUSSIAN:
|
||||
ret = LanguageType::RUSSIAN;
|
||||
break;
|
||||
case LANG_KOREAN:
|
||||
ret = LanguageType::KOREAN;
|
||||
break;
|
||||
case LANG_JAPANESE:
|
||||
ret = LanguageType::JAPANESE;
|
||||
break;
|
||||
case LANG_HUNGARIAN:
|
||||
ret = LanguageType::HUNGARIAN;
|
||||
break;
|
||||
case LANG_PORTUGUESE:
|
||||
ret = LanguageType::PORTUGUESE;
|
||||
break;
|
||||
case LANG_ARABIC:
|
||||
ret = LanguageType::ARABIC;
|
||||
break;
|
||||
case LANG_NORWEGIAN:
|
||||
ret = LanguageType::NORWEGIAN;
|
||||
break;
|
||||
case LANG_POLISH:
|
||||
ret = LanguageType::POLISH;
|
||||
break;
|
||||
case LANG_TURKISH:
|
||||
ret = LanguageType::TURKISH;
|
||||
break;
|
||||
case LANG_UKRAINIAN:
|
||||
ret = LanguageType::UKRAINIAN;
|
||||
break;
|
||||
case LANG_ROMANIAN:
|
||||
ret = LanguageType::ROMANIAN;
|
||||
break;
|
||||
case LANG_BULGARIAN:
|
||||
ret = LanguageType::BULGARIAN;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string Application::getCurrentLanguageCode() const
|
||||
{
|
||||
LANGID lid = GetUserDefaultUILanguage();
|
||||
const LCID locale_id = MAKELCID(lid, SORT_DEFAULT);
|
||||
int length = GetLocaleInfoA(locale_id, LOCALE_SISO639LANGNAME, nullptr, 0);
|
||||
|
||||
char *tempCode = new char[length];
|
||||
GetLocaleInfoA(locale_id, LOCALE_SISO639LANGNAME, tempCode, length);
|
||||
std::string code = tempCode;
|
||||
delete tempCode;
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
bool Application::isDisplayStats() {
|
||||
se::AutoHandleScope hs;
|
||||
se::Value ret;
|
||||
char commandBuf[100] = "cc.debug.isDisplayStats();";
|
||||
se::ScriptEngine::getInstance()->evalString(commandBuf, 100, &ret);
|
||||
return ret.toBoolean();
|
||||
}
|
||||
|
||||
void Application::setDisplayStats(bool isShow) {
|
||||
se::AutoHandleScope hs;
|
||||
char commandBuf[100] = {0};
|
||||
sprintf(commandBuf, "cc.debug.setDisplayStats(%s);", isShow ? "true" : "false");
|
||||
se::ScriptEngine::getInstance()->evalString(commandBuf);
|
||||
}
|
||||
|
||||
float Application::getScreenScale() const
|
||||
{
|
||||
return CAST_VIEW(_view)->getScale();
|
||||
}
|
||||
|
||||
GLint Application::getMainFBO() const
|
||||
{
|
||||
return CAST_VIEW(_view)->getMainFBO();
|
||||
}
|
||||
|
||||
Application::Platform Application::getPlatform() const
|
||||
{
|
||||
return Platform::WINDOWS;
|
||||
}
|
||||
|
||||
bool Application::openURL(const std::string &url)
|
||||
{
|
||||
WCHAR *temp = new WCHAR[url.size() + 1];
|
||||
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, url.c_str(), url.size() + 1, temp, url.size() + 1);
|
||||
HINSTANCE r = ShellExecuteW(NULL, L"open", temp, NULL, NULL, SW_SHOWNORMAL);
|
||||
delete[] temp;
|
||||
return (size_t)r>32;
|
||||
}
|
||||
|
||||
void Application::copyTextToClipboard(const std::string &text)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
bool Application::applicationDidFinishLaunching()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::onPause()
|
||||
{
|
||||
}
|
||||
|
||||
void Application::onResume()
|
||||
{
|
||||
}
|
||||
|
||||
void Application::setMultitouch(bool)
|
||||
{
|
||||
}
|
||||
|
||||
void Application::onCreateView(PixelFormat& pixelformat, DepthFormat& depthFormat, int& multisamplingCount)
|
||||
{
|
||||
pixelformat = PixelFormat::RGBA8;
|
||||
depthFormat = DepthFormat::DEPTH24_STENCIL8;
|
||||
|
||||
multisamplingCount = 0;
|
||||
}
|
||||
|
||||
void Application::createView(const std::string& name, int width, int height)
|
||||
{
|
||||
int multisamplingCount = 0;
|
||||
PixelFormat pixelformat;
|
||||
DepthFormat depthFormat;
|
||||
|
||||
onCreateView(pixelformat,
|
||||
depthFormat,
|
||||
multisamplingCount);
|
||||
|
||||
_view = new GLView(this, name, 0, 0, width, height, pixelformat, depthFormat, multisamplingCount);
|
||||
}
|
||||
|
||||
std::string Application::getSystemVersion()
|
||||
{
|
||||
// REFINE
|
||||
return std::string("unknown Windows version");
|
||||
}
|
||||
NS_CC_END
|
||||
@@ -0,0 +1,917 @@
|
||||
#include "platform/CCCanvasRenderingContext2D.h"
|
||||
#include "base/ccTypes.h"
|
||||
#include "base/csscolorparser.hpp"
|
||||
|
||||
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "cocos/scripting/js-bindings/manual/jsb_platform.h"
|
||||
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include <regex>
|
||||
|
||||
using namespace cocos2d;
|
||||
|
||||
enum class CanvasTextAlign {
|
||||
LEFT,
|
||||
CENTER,
|
||||
RIGHT
|
||||
};
|
||||
|
||||
enum class CanvasTextBaseline {
|
||||
TOP,
|
||||
MIDDLE,
|
||||
BOTTOM
|
||||
};
|
||||
|
||||
namespace {
|
||||
void fillRectWithColor(uint8_t* buf, uint32_t totalWidth, uint32_t totalHeight, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
assert(x + width <= totalWidth);
|
||||
assert(y + height <= totalHeight);
|
||||
|
||||
uint32_t y0 = y;
|
||||
uint32_t y1 = y + height;
|
||||
uint8_t* p;
|
||||
for (uint32_t offsetY = y0; offsetY < y1; ++offsetY)
|
||||
{
|
||||
for (uint32_t offsetX = x; offsetX < (x + width); ++offsetX)
|
||||
{
|
||||
p = buf + (totalWidth * offsetY + offsetX) * 4;
|
||||
*p++ = r;
|
||||
*p++ = g;
|
||||
*p++ = b;
|
||||
*p++ = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CanvasRenderingContext2DImpl
|
||||
{
|
||||
public:
|
||||
CanvasRenderingContext2DImpl() : _DC(nullptr)
|
||||
, _bmp(nullptr)
|
||||
, _font((HFONT)GetStockObject(DEFAULT_GUI_FONT))
|
||||
, _wnd(nullptr)
|
||||
, _savedDC(0)
|
||||
{
|
||||
_wnd = nullptr;
|
||||
HDC hdc = GetDC(_wnd);
|
||||
_DC = CreateCompatibleDC(hdc);
|
||||
ReleaseDC(_wnd, hdc);
|
||||
}
|
||||
|
||||
~CanvasRenderingContext2DImpl()
|
||||
{
|
||||
_deleteBitmap();
|
||||
_removeCustomFont();
|
||||
if (_DC)
|
||||
DeleteDC(_DC);
|
||||
}
|
||||
|
||||
void recreateBuffer(float w, float h)
|
||||
{
|
||||
_bufferWidth = w;
|
||||
_bufferHeight = h;
|
||||
if (_bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
{
|
||||
_deleteBitmap();
|
||||
return;
|
||||
}
|
||||
|
||||
int textureSize = _bufferWidth * _bufferHeight * 4;
|
||||
uint8_t* data = (uint8_t*)malloc(sizeof(uint8_t) * textureSize);
|
||||
memset(data, 0x00, textureSize);
|
||||
_imageData.fastSet(data, textureSize);
|
||||
|
||||
_prepareBitmap(_bufferWidth, _bufferHeight);
|
||||
}
|
||||
|
||||
void beginPath()
|
||||
{
|
||||
// called: set_lineWidth() -> beginPath() -> moveTo() -> lineTo() -> stroke(), when draw line
|
||||
_hpen = CreatePen(PS_SOLID, _lineWidth, RGB(255, 255, 255));
|
||||
// the return value of SelectObject is a handle to the object being replaced, so we should delete them to avoid memory leak
|
||||
HGDIOBJ hOldPen = SelectObject(_DC, _hpen);
|
||||
HGDIOBJ hOldBmp = SelectObject(_DC, _bmp);
|
||||
DeleteObject(hOldPen);
|
||||
DeleteObject(hOldBmp);
|
||||
|
||||
SetBkMode(_DC, TRANSPARENT);
|
||||
}
|
||||
|
||||
void closePath()
|
||||
{
|
||||
}
|
||||
|
||||
void moveTo(float x, float y)
|
||||
{
|
||||
MoveToEx(_DC, x, -(y - _bufferHeight - _fontSize), nullptr);
|
||||
}
|
||||
|
||||
void lineTo(float x, float y)
|
||||
{
|
||||
LineTo(_DC, x, -(y - _bufferHeight - _fontSize));
|
||||
}
|
||||
|
||||
void stroke()
|
||||
{
|
||||
DeleteObject(_hpen);
|
||||
if (_bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
_fillTextureData();
|
||||
}
|
||||
|
||||
void saveContext()
|
||||
{
|
||||
_savedDC = SaveDC(_DC);
|
||||
}
|
||||
|
||||
void restoreContext()
|
||||
{
|
||||
BOOL ret = RestoreDC(_DC, _savedDC);
|
||||
if (0 == ret)
|
||||
{
|
||||
SE_LOGD("CanvasRenderingContext2DImpl restore context failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void clearRect(float x, float y, float w, float h)
|
||||
{
|
||||
if (_bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
if (_imageData.isNull())
|
||||
return;
|
||||
|
||||
recreateBuffer(w, h);
|
||||
}
|
||||
|
||||
void fillRect(float x, float y, float w, float h)
|
||||
{
|
||||
if (_bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
|
||||
//not filled all Bits in buffer? the buffer length is _bufferWidth * _bufferHeight * 4, but it filled _bufferWidth * _bufferHeight * 3?
|
||||
uint8_t* buffer = _imageData.getBytes();
|
||||
if (buffer)
|
||||
{
|
||||
uint8_t r = _fillStyle.r * 255.0f;
|
||||
uint8_t g = _fillStyle.g * 255.0f;
|
||||
uint8_t b = _fillStyle.b * 255.0f;
|
||||
uint8_t a = _fillStyle.a * 255.0f;
|
||||
fillRectWithColor(buffer, (uint32_t)_bufferWidth, (uint32_t)_bufferHeight, (uint32_t)x, (uint32_t)y, (uint32_t)w, (uint32_t)h, r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
void fillText(const std::string& text, float x, float y, float maxWidth)
|
||||
{
|
||||
if (text.empty() || _bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
|
||||
SIZE textSize = { 0, 0 };
|
||||
Point offsetPoint = _convertDrawPoint(Point(x, y), text);
|
||||
|
||||
_drawText(text, (int)offsetPoint.x, (int)offsetPoint.y);
|
||||
_fillTextureData();
|
||||
|
||||
}
|
||||
|
||||
void strokeText(const std::string& text, float x, float y, float maxWidth)
|
||||
{
|
||||
if (text.empty() || _bufferWidth < 1.0f || _bufferHeight < 1.0f)
|
||||
return;
|
||||
// REFINE
|
||||
}
|
||||
|
||||
cocos2d::Size measureText(const std::string& text)
|
||||
{
|
||||
if (text.empty())
|
||||
return Size(0.0f, 0.0f);
|
||||
|
||||
int bufferLen = 0;
|
||||
wchar_t * pwszBuffer = _utf8ToUtf16(text, &bufferLen);
|
||||
SIZE size = _sizeWithText(pwszBuffer, bufferLen);
|
||||
//SE_LOGD("CanvasRenderingContext2DImpl::measureText: %s, %d, %d\n", text.c_str(), size.cx, size.cy);
|
||||
CC_SAFE_DELETE_ARRAY(pwszBuffer);
|
||||
return Size(size.cx, size.cy);
|
||||
}
|
||||
|
||||
void updateFont(const std::string& fontName, float fontSize, bool bold = false)
|
||||
{
|
||||
do
|
||||
{
|
||||
_fontName = fontName;
|
||||
_fontSize = fontSize;
|
||||
std::string fontPath;
|
||||
LOGFONTA tFont = { 0 };
|
||||
if (!_fontName.empty())
|
||||
{
|
||||
// firstly, try to create font from ttf file
|
||||
const auto& fontInfoMap = getFontFamilyNameMap();
|
||||
auto iter = fontInfoMap.find(_fontName);
|
||||
if (iter != fontInfoMap.end())
|
||||
{
|
||||
fontPath = iter->second;
|
||||
std::string tmpFontPath = fontPath;
|
||||
int nFindPos = tmpFontPath.rfind("/");
|
||||
tmpFontPath = &tmpFontPath[nFindPos + 1];
|
||||
nFindPos = tmpFontPath.rfind(".");
|
||||
// IDEA: draw ttf failed if font file name not equal font face name
|
||||
// for example: "DejaVuSansMono-Oblique" not equal "DejaVu Sans Mono" when using DejaVuSansMono-Oblique.ttf
|
||||
_fontName = tmpFontPath.substr(0, nFindPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto nFindPos = fontName.rfind("/");
|
||||
if (nFindPos != fontName.npos)
|
||||
{
|
||||
if (fontName.length() == nFindPos + 1)
|
||||
{
|
||||
_fontName = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
_fontName = &_fontName[nFindPos + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
tFont.lfCharSet = DEFAULT_CHARSET;
|
||||
strcpy_s(tFont.lfFaceName, LF_FACESIZE, _fontName.c_str());
|
||||
}
|
||||
|
||||
if (_fontSize)
|
||||
tFont.lfHeight = -_fontSize;
|
||||
|
||||
if (bold)
|
||||
tFont.lfWeight = FW_BOLD;
|
||||
else
|
||||
tFont.lfWeight = FW_NORMAL;
|
||||
|
||||
// disable Cleartype
|
||||
tFont.lfQuality = ANTIALIASED_QUALITY;
|
||||
|
||||
// delete old font
|
||||
_removeCustomFont();
|
||||
|
||||
if (fontPath.size() > 0)
|
||||
{
|
||||
_curFontPath = fontPath;
|
||||
wchar_t * pwszBuffer = _utf8ToUtf16(_curFontPath);
|
||||
if (pwszBuffer)
|
||||
{
|
||||
if (AddFontResource(pwszBuffer))
|
||||
{
|
||||
SendMessage(_wnd, WM_FONTCHANGE, 0, 0);
|
||||
}
|
||||
delete[] pwszBuffer;
|
||||
pwszBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// create new font
|
||||
_font = CreateFontIndirectA(&tFont);
|
||||
if (!_font)
|
||||
{
|
||||
// create failed, use default font
|
||||
SE_LOGE("Failed to create custom font(font name: %s, font size: %f), use default font.\n",
|
||||
_fontName.c_str(), fontSize);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectObject(_DC, _font);
|
||||
SendMessage(_wnd, WM_FONTCHANGE, 0, 0);
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
|
||||
void setTextAlign(CanvasTextAlign align)
|
||||
{
|
||||
_textAlign = align;
|
||||
}
|
||||
|
||||
void setTextBaseline(CanvasTextBaseline baseline)
|
||||
{
|
||||
_textBaseLine = baseline;
|
||||
}
|
||||
|
||||
void setFillStyle(float r, float g, float b, float a)
|
||||
{
|
||||
_fillStyle.r = r;
|
||||
_fillStyle.g = g;
|
||||
_fillStyle.b = b;
|
||||
_fillStyle.a = a;
|
||||
}
|
||||
|
||||
void setStrokeStyle(float r, float g, float b, float a)
|
||||
{
|
||||
_strokeStyle.r = r;
|
||||
_strokeStyle.g = g;
|
||||
_strokeStyle.b = b;
|
||||
_strokeStyle.a = a;
|
||||
}
|
||||
|
||||
void setLineWidth(float lineWidth)
|
||||
{
|
||||
_lineWidth = lineWidth;
|
||||
}
|
||||
|
||||
void setPremultiply(bool multiply)
|
||||
{
|
||||
_premultiply = multiply;
|
||||
}
|
||||
|
||||
const Data& getDataRef() const
|
||||
{
|
||||
return _imageData;
|
||||
}
|
||||
|
||||
HDC _DC;
|
||||
HBITMAP _bmp;
|
||||
private:
|
||||
|
||||
Data _imageData;
|
||||
HFONT _font;
|
||||
HWND _wnd;
|
||||
HPEN _hpen;
|
||||
PAINTSTRUCT _paintStruct;
|
||||
std::string _curFontPath;
|
||||
int _savedDC;
|
||||
float _lineWidth = 0.0f;
|
||||
float _bufferWidth = 0.0f;
|
||||
float _bufferHeight = 0.0f;
|
||||
bool _premultiply = true;
|
||||
|
||||
std::string _fontName;
|
||||
int _fontSize;
|
||||
SIZE _textSize;
|
||||
CanvasTextAlign _textAlign;
|
||||
CanvasTextBaseline _textBaseLine;
|
||||
cocos2d::Color4F _fillStyle;
|
||||
cocos2d::Color4F _strokeStyle;
|
||||
|
||||
TEXTMETRIC _tm;
|
||||
|
||||
// change utf-8 string to utf-16, pRetLen is the string length after changing
|
||||
wchar_t * _utf8ToUtf16(const std::string& str, int * pRetLen = nullptr)
|
||||
{
|
||||
wchar_t * pwszBuffer = nullptr;
|
||||
do
|
||||
{
|
||||
if (str.empty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
int nLen = str.size();
|
||||
int nBufLen = nLen + 1;
|
||||
pwszBuffer = new wchar_t[nBufLen];
|
||||
CC_BREAK_IF(!pwszBuffer);
|
||||
memset(pwszBuffer, 0, sizeof(wchar_t) * nBufLen);
|
||||
// str.size() not equal actuallyLen for Chinese char
|
||||
int actuallyLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), nLen, pwszBuffer, nBufLen);
|
||||
// SE_LOGE("_utf8ToUtf16, str:%s, strLen:%d, retLen:%d\n", str.c_str(), str.size(), actuallyLen);
|
||||
if (pRetLen != nullptr) {
|
||||
*pRetLen = actuallyLen;
|
||||
}
|
||||
} while (0);
|
||||
return pwszBuffer;
|
||||
|
||||
}
|
||||
|
||||
void _removeCustomFont()
|
||||
{
|
||||
HFONT hDefFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
|
||||
if (hDefFont != _font)
|
||||
{
|
||||
DeleteObject(SelectObject(_DC, hDefFont));
|
||||
}
|
||||
// release temp font resource
|
||||
if (_curFontPath.size() > 0)
|
||||
{
|
||||
wchar_t * pwszBuffer = _utf8ToUtf16(_curFontPath);
|
||||
if (pwszBuffer)
|
||||
{
|
||||
RemoveFontResource(pwszBuffer);
|
||||
SendMessage(_wnd, WM_FONTCHANGE, 0, 0);
|
||||
delete[] pwszBuffer;
|
||||
pwszBuffer = nullptr;
|
||||
}
|
||||
_curFontPath.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// x, y offset value
|
||||
int _drawText(const std::string& text, int x, int y)
|
||||
{
|
||||
int nRet = 0;
|
||||
wchar_t * pwszBuffer = nullptr;
|
||||
do
|
||||
{
|
||||
CC_BREAK_IF(text.empty());
|
||||
|
||||
DWORD dwFmt = DT_SINGLELINE | DT_NOPREFIX;
|
||||
|
||||
int bufferLen = 0;
|
||||
pwszBuffer = _utf8ToUtf16(text, &bufferLen);
|
||||
|
||||
SIZE newSize = _sizeWithText(pwszBuffer, bufferLen);
|
||||
|
||||
_textSize = newSize;
|
||||
|
||||
RECT rcText = { 0 };
|
||||
|
||||
rcText.right = newSize.cx;
|
||||
rcText.bottom = newSize.cy;
|
||||
|
||||
LONG offsetX = x;
|
||||
LONG offsetY = y;
|
||||
if (offsetX || offsetY)
|
||||
{
|
||||
OffsetRect(&rcText, offsetX, offsetY);
|
||||
}
|
||||
|
||||
// SE_LOGE("_drawText text,%s size: (%d, %d) offset after convert: (%d, %d) \n", text.c_str(), newSize.cx, newSize.cy, offsetX, offsetY);
|
||||
|
||||
SetBkMode(_DC, TRANSPARENT);
|
||||
SetTextColor(_DC, RGB(255, 255, 255)); // white color
|
||||
|
||||
// draw text
|
||||
nRet = DrawTextW(_DC, pwszBuffer, bufferLen, &rcText, dwFmt);
|
||||
} while (0);
|
||||
CC_SAFE_DELETE_ARRAY(pwszBuffer);
|
||||
|
||||
return nRet;
|
||||
}
|
||||
|
||||
SIZE _sizeWithText(const wchar_t * pszText, int nLen)
|
||||
{
|
||||
SIZE tRet = { 0 };
|
||||
do
|
||||
{
|
||||
CC_BREAK_IF(!pszText || nLen <= 0);
|
||||
|
||||
RECT rc = { 0, 0, 0, 0 };
|
||||
DWORD dwCalcFmt = DT_CALCRECT | DT_NOPREFIX;
|
||||
|
||||
// measure text size
|
||||
DrawTextW(_DC, pszText, nLen, &rc, dwCalcFmt);
|
||||
|
||||
tRet.cx = rc.right;
|
||||
tRet.cy = rc.bottom;
|
||||
} while (0);
|
||||
|
||||
return tRet;
|
||||
}
|
||||
|
||||
void _prepareBitmap(int nWidth, int nHeight)
|
||||
{
|
||||
// release bitmap
|
||||
_deleteBitmap();
|
||||
|
||||
if (nWidth > 0 && nHeight > 0)
|
||||
{
|
||||
_bmp = CreateBitmap(nWidth, nHeight, 1, 32, nullptr);
|
||||
SelectObject(_DC, _bmp);
|
||||
}
|
||||
}
|
||||
|
||||
void _deleteBitmap()
|
||||
{
|
||||
if (_bmp)
|
||||
{
|
||||
DeleteObject(_bmp);
|
||||
_bmp = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void _fillTextureData()
|
||||
{
|
||||
do
|
||||
{
|
||||
int dataLen = _bufferWidth * _bufferHeight * 4;
|
||||
unsigned char* dataBuf = (unsigned char*)malloc(sizeof(unsigned char) * dataLen);
|
||||
CC_BREAK_IF(!dataBuf);
|
||||
unsigned char* imageBuf = _imageData.getBytes();
|
||||
CC_BREAK_IF(!imageBuf);
|
||||
|
||||
struct
|
||||
{
|
||||
BITMAPINFOHEADER bmiHeader;
|
||||
int mask[4];
|
||||
} bi = { 0 };
|
||||
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
|
||||
CC_BREAK_IF(!GetDIBits(_DC, _bmp, 0, 0,
|
||||
nullptr, (LPBITMAPINFO)&bi, DIB_RGB_COLORS));
|
||||
|
||||
// copy pixel data
|
||||
bi.bmiHeader.biHeight = (bi.bmiHeader.biHeight > 0) ? -bi.bmiHeader.biHeight : bi.bmiHeader.biHeight;
|
||||
GetDIBits(_DC, _bmp, 0, _bufferHeight, dataBuf,
|
||||
(LPBITMAPINFO)&bi, DIB_RGB_COLORS);
|
||||
|
||||
|
||||
uint8_t r = _fillStyle.r * 255;
|
||||
uint8_t g = _fillStyle.g * 255;
|
||||
uint8_t b = _fillStyle.b * 255;
|
||||
uint8_t a = _fillStyle.a;
|
||||
COLORREF textColor = (b << 16 | g << 8 | r) & 0x00ffffff;
|
||||
COLORREF * pPixel = nullptr;
|
||||
COLORREF * pImage = nullptr;
|
||||
|
||||
if (_premultiply)
|
||||
{
|
||||
uint8_t dirtyValue = 0;
|
||||
for (int y = 0; y < _bufferHeight; ++y)
|
||||
{
|
||||
pPixel = (COLORREF *)dataBuf + y * (int)_bufferWidth;
|
||||
pImage = (COLORREF *)imageBuf + y * (int)_bufferWidth;
|
||||
for (int x = 0; x < _bufferWidth; ++x)
|
||||
{
|
||||
COLORREF& clr = *pPixel;
|
||||
COLORREF& val = *pImage;
|
||||
dirtyValue = GetRValue(clr);
|
||||
// "dirtyValue > 0" means pixel was covered when drawing text
|
||||
if (dirtyValue > 0)
|
||||
{
|
||||
// r = _fillStyle.r * 255 * (dirtyValue / 255) * alpha;
|
||||
r = _fillStyle.r * dirtyValue * a;
|
||||
g = _fillStyle.g * dirtyValue * a;
|
||||
b = _fillStyle.b * dirtyValue * a;
|
||||
textColor = (b << 16 | g << 8 | r) & 0x00ffffff;
|
||||
val = ((BYTE)(dirtyValue * a) << 24) | textColor;
|
||||
}
|
||||
++pPixel;
|
||||
++pImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = 0; y < _bufferHeight; ++y)
|
||||
{
|
||||
pPixel = (COLORREF *)dataBuf + y * (int)_bufferWidth;
|
||||
pImage = (COLORREF *)imageBuf + y * (int)_bufferWidth;
|
||||
for (int x = 0; x < _bufferWidth; ++x)
|
||||
{
|
||||
COLORREF& clr = *pPixel;
|
||||
COLORREF& val = *pImage;
|
||||
// Because text is drawn in white color, and background color is black,
|
||||
// so the red value is equal to alpha value. And we should keep this value
|
||||
// as it includes anti-atlas information.
|
||||
uint8_t alpha = GetRValue(clr);
|
||||
|
||||
if (alpha > 0)
|
||||
{
|
||||
val = (alpha << 24) | textColor;
|
||||
}
|
||||
|
||||
++pPixel;
|
||||
++pImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(dataBuf);
|
||||
} while (0);
|
||||
}
|
||||
|
||||
Point _convertDrawPoint(Point point, std::string text) {
|
||||
Size textSize = measureText(text);
|
||||
if (_textAlign == CanvasTextAlign::CENTER)
|
||||
{
|
||||
point.x -= textSize.width / 2.0f;
|
||||
}
|
||||
else if (_textAlign == CanvasTextAlign::RIGHT)
|
||||
{
|
||||
point.x -= textSize.width;
|
||||
}
|
||||
|
||||
if (_textBaseLine == CanvasTextBaseline::TOP)
|
||||
{
|
||||
point.y += _fontSize;
|
||||
}
|
||||
else if (_textBaseLine == CanvasTextBaseline::MIDDLE)
|
||||
{
|
||||
point.y += _fontSize / 2.0f;
|
||||
}
|
||||
|
||||
// Since the web platform cannot get the baseline of the font, an additive offset is performed for all platforms.
|
||||
// That's why we should add baseline back again on other platforms
|
||||
GetTextMetrics(_DC, &_tm);
|
||||
point.y -= _tm.tmAscent;
|
||||
|
||||
return point;
|
||||
}
|
||||
};
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
CanvasGradient::CanvasGradient()
|
||||
{
|
||||
//SE_LOGD("CanvasGradient constructor: %p\n", this);
|
||||
}
|
||||
|
||||
CanvasGradient::~CanvasGradient()
|
||||
{
|
||||
//SE_LOGD("CanvasGradient destructor: %p\n", this);
|
||||
}
|
||||
|
||||
void CanvasGradient::addColorStop(float offset, const std::string& color)
|
||||
{
|
||||
//SE_LOGD("CanvasGradient::addColorStop: %p\n", this);
|
||||
}
|
||||
|
||||
// CanvasRenderingContext2D
|
||||
|
||||
CanvasRenderingContext2D::CanvasRenderingContext2D(float width, float height)
|
||||
: __width(width)
|
||||
, __height(height)
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D constructor: %p, width: %f, height: %f\n", this, width, height);
|
||||
_impl = new CanvasRenderingContext2DImpl();
|
||||
recreateBufferIfNeeded();
|
||||
}
|
||||
|
||||
CanvasRenderingContext2D::~CanvasRenderingContext2D()
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D destructor: %p\n", this);
|
||||
delete _impl;
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::recreateBufferIfNeeded()
|
||||
{
|
||||
if (_isBufferSizeDirty)
|
||||
{
|
||||
_isBufferSizeDirty = false;
|
||||
//SE_LOGD("Recreate buffer %p, w: %f, h:%f\n", this, __width, __height);
|
||||
_impl->recreateBuffer(__width, __height);
|
||||
if (_canvasBufferUpdatedCB != nullptr)
|
||||
_canvasBufferUpdatedCB(_impl->getDataRef());
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height)
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::clearRect: %p, %f, %f, %f, %f\n", this, x, y, width, height);
|
||||
recreateBufferIfNeeded();
|
||||
_impl->clearRect(x, y, width, height);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::fillRect(float x, float y, float width, float height)
|
||||
{
|
||||
recreateBufferIfNeeded();
|
||||
_impl->fillRect(x, y, width, height);
|
||||
|
||||
if (_canvasBufferUpdatedCB != nullptr)
|
||||
_canvasBufferUpdatedCB(_impl->getDataRef());
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::fillText(const std::string& text, float x, float y, float maxWidth)
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::fillText: %s, offset: (%f, %f), %f\n", text.c_str(), x, y, maxWidth);
|
||||
if (text.empty())
|
||||
return;
|
||||
recreateBufferIfNeeded();
|
||||
|
||||
_impl->fillText(text, x, y, maxWidth);
|
||||
if (_canvasBufferUpdatedCB != nullptr)
|
||||
_canvasBufferUpdatedCB(_impl->getDataRef());
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::strokeText(const std::string& text, float x, float y, float maxWidth)
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::strokeText: %s, %f, %f, %f\n", text.c_str(), x, y, maxWidth);
|
||||
if (text.empty())
|
||||
return;
|
||||
recreateBufferIfNeeded();
|
||||
|
||||
_impl->strokeText(text, x, y, maxWidth);
|
||||
|
||||
if (_canvasBufferUpdatedCB != nullptr)
|
||||
_canvasBufferUpdatedCB(_impl->getDataRef());
|
||||
}
|
||||
|
||||
cocos2d::Size CanvasRenderingContext2D::measureText(const std::string& text)
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::measureText: %s\n", text.c_str());
|
||||
return _impl->measureText(text);
|
||||
}
|
||||
|
||||
CanvasGradient* CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::save()
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::save\n");
|
||||
_impl->saveContext();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::beginPath()
|
||||
{
|
||||
//SE_LOGD("\n-----------begin------------------\nCanvasRenderingContext2D::beginPath\n");
|
||||
_impl->beginPath();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::closePath()
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::closePath\n");
|
||||
_impl->closePath();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::moveTo(float x, float y)
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::moveTo\n");
|
||||
_impl->moveTo(x, y);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::lineTo(float x, float y)
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::lineTo\n");
|
||||
_impl->lineTo(x, y);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::stroke()
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::stroke\n");
|
||||
_impl->stroke();
|
||||
|
||||
if (_canvasBufferUpdatedCB != nullptr)
|
||||
_canvasBufferUpdatedCB(_impl->getDataRef());
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::restore()
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::restore\n");
|
||||
_impl->restoreContext();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::setCanvasBufferUpdatedCallback(const CanvasBufferUpdatedCallback& cb)
|
||||
{
|
||||
_canvasBufferUpdatedCB = cb;
|
||||
}
|
||||
void CanvasRenderingContext2D::setPremultiply(bool multiply)
|
||||
{
|
||||
_impl->setPremultiply(_premultiply);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set__width(float width)
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::set__width: %f\n", width);
|
||||
__width = width;
|
||||
_isBufferSizeDirty = true;
|
||||
recreateBufferIfNeeded();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set__height(float height)
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::set__height: %f\n", height);
|
||||
__height = height;
|
||||
_isBufferSizeDirty = true;
|
||||
recreateBufferIfNeeded();
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_lineWidth(float lineWidth)
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::set_lineWidth %d\n", lineWidth);
|
||||
_lineWidth = lineWidth;
|
||||
_impl->setLineWidth(lineWidth);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_lineCap(const std::string& lineCap)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_lineJoin(const std::string& lineJoin)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::fill()
|
||||
{
|
||||
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
void CanvasRenderingContext2D::rect(float x, float y, float w, float h)
|
||||
{
|
||||
// SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_font(const std::string& font)
|
||||
{
|
||||
if (_font != font)
|
||||
{
|
||||
_font = font;
|
||||
|
||||
std::string boldStr;
|
||||
std::string fontName = "Arial";
|
||||
std::string fontSizeStr = "30";
|
||||
|
||||
// support get font name from `60px American` or `60px "American abc-abc_abc"`
|
||||
std::regex re("(bold)?\\s*((\\d+)([\\.]\\d+)?)px\\s+([\\w-]+|\"[\\w -]+\"$)");
|
||||
std::match_results<std::string::const_iterator> results;
|
||||
if (std::regex_search(_font.cbegin(), _font.cend(), results, re))
|
||||
{
|
||||
boldStr = results[1].str();
|
||||
fontSizeStr = results[2].str();
|
||||
fontName = results[5].str();
|
||||
}
|
||||
|
||||
float fontSize = atof(fontSizeStr.c_str());
|
||||
//SE_LOGD("CanvasRenderingContext2D::set_font: %s, Size: %f, isBold: %b\n", fontName.c_str(), fontSize, !boldStr.empty());
|
||||
_impl->updateFont(fontName, fontSize, !boldStr.empty());
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_textAlign(const std::string& textAlign)
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::set_textAlign: %s\n", textAlign.c_str());
|
||||
if (textAlign == "left")
|
||||
{
|
||||
_impl->setTextAlign(CanvasTextAlign::LEFT);
|
||||
}
|
||||
else if (textAlign == "center" || textAlign == "middle")
|
||||
{
|
||||
_impl->setTextAlign(CanvasTextAlign::CENTER);
|
||||
}
|
||||
else if (textAlign == "right")
|
||||
{
|
||||
_impl->setTextAlign(CanvasTextAlign::RIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_textBaseline(const std::string& textBaseline)
|
||||
{
|
||||
//SE_LOGD("CanvasRenderingContext2D::set_textBaseline: %s\n", textBaseline.c_str());
|
||||
if (textBaseline == "top")
|
||||
{
|
||||
_impl->setTextBaseline(CanvasTextBaseline::TOP);
|
||||
}
|
||||
else if (textBaseline == "middle")
|
||||
{
|
||||
_impl->setTextBaseline(CanvasTextBaseline::MIDDLE);
|
||||
}
|
||||
else if (textBaseline == "bottom" || textBaseline == "alphabetic") //REFINE:, how to deal with alphabetic, currently we handle it as bottom mode.
|
||||
{
|
||||
_impl->setTextBaseline(CanvasTextBaseline::BOTTOM);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_fillStyle(const std::string& fillStyle)
|
||||
{
|
||||
CSSColorParser::Color color = CSSColorParser::parse(fillStyle);
|
||||
_impl->setFillStyle(color.r/255.0f, color.g/255.0f, color.b/255.0f, color.a);
|
||||
//SE_LOGD("CanvasRenderingContext2D::set_fillStyle: %s, (%d, %d, %d, %f)\n", fillStyle.c_str(), color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_strokeStyle(const std::string& strokeStyle)
|
||||
{
|
||||
CSSColorParser::Color color = CSSColorParser::parse(strokeStyle);
|
||||
_impl->setStrokeStyle(color.r/255.0f, color.g/255.0f, color.b/255.0f, color.a);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::set_globalCompositeOperation(const std::string& globalCompositeOperation)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::_fillImageData(const Data& imageData, float imageWidth, float imageHeight, float offsetX, float offsetY)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
// transform
|
||||
//REFINE:
|
||||
|
||||
void CanvasRenderingContext2D::translate(float x, float y)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::scale(float x, float y)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::rotate(float angle)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::transform(float a, float b, float c, float d, float e, float f)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::setTransform(float a, float b, float c, float d, float e, float f)
|
||||
{
|
||||
//SE_LOGE("%s isn't implemented!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
107
cocos2d-x/cocos/platform/win32/CCDevice-win32.cpp
Normal file
107
cocos2d-x/cocos/platform/win32/CCDevice-win32.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
||||
#include "platform/CCDevice.h"
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include "platform/CCStdC.h"
|
||||
#include "platform/CCApplication.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
int Device::getDPI()
|
||||
{
|
||||
static int dpi = -1;
|
||||
if (dpi == -1)
|
||||
{
|
||||
HDC hScreenDC = GetDC( nullptr );
|
||||
int PixelsX = GetDeviceCaps( hScreenDC, HORZRES );
|
||||
int MMX = GetDeviceCaps( hScreenDC, HORZSIZE );
|
||||
ReleaseDC( nullptr, hScreenDC );
|
||||
dpi = 254.0f*PixelsX/MMX/10;
|
||||
}
|
||||
return dpi;
|
||||
}
|
||||
|
||||
void Device::setAccelerometerEnabled(bool isEnabled)
|
||||
{}
|
||||
|
||||
void Device::setAccelerometerInterval(float interval)
|
||||
{}
|
||||
|
||||
const Device::MotionValue & Device::getDeviceMotionValue()
|
||||
{
|
||||
static MotionValue __motionValue;
|
||||
return __motionValue;
|
||||
}
|
||||
|
||||
Device::Rotation Device::getDeviceRotation()
|
||||
{
|
||||
return Device::Rotation::_0;
|
||||
}
|
||||
|
||||
std::string Device::getDeviceModel()
|
||||
{
|
||||
// REFINE
|
||||
return std::string("Windows");
|
||||
}
|
||||
|
||||
void Device::setKeepScreenOn(bool value)
|
||||
{
|
||||
CC_UNUSED_PARAM(value);
|
||||
}
|
||||
|
||||
void Device::vibrate(float duration)
|
||||
{
|
||||
CC_UNUSED_PARAM(duration);
|
||||
}
|
||||
|
||||
float Device::getBatteryLevel()
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
Device::NetworkType Device::getNetworkType()
|
||||
{
|
||||
return Device::NetworkType::LAN;
|
||||
}
|
||||
|
||||
cocos2d::Vec4 Device::getSafeAreaEdge()
|
||||
{
|
||||
// no SafeArea concept on win32, return ZERO Vec4.
|
||||
return cocos2d::Vec4();
|
||||
}
|
||||
|
||||
int Device::getDevicePixelRatio()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
429
cocos2d-x/cocos/platform/win32/CCFileUtils-win32.cpp
Normal file
429
cocos2d-x/cocos/platform/win32/CCFileUtils-win32.cpp
Normal file
@@ -0,0 +1,429 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
||||
#include "platform/win32/CCFileUtils-win32.h"
|
||||
#include "platform/win32/CCUtils-win32.h"
|
||||
#include <Shlobj.h>
|
||||
#include <cstdlib>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
#define CC_MAX_PATH 512
|
||||
|
||||
// The root path of resources, the character encoding is UTF-8.
|
||||
// UTF-8 is the only encoding supported by cocos2d-x API.
|
||||
static std::string s_resourcePath = "";
|
||||
|
||||
// D:\aaa\bbb\ccc\ddd\abc.txt --> D:/aaa/bbb/ccc/ddd/abc.txt
|
||||
static inline std::string convertPathFormatToUnixStyle(const std::string& path)
|
||||
{
|
||||
std::string ret = path;
|
||||
int len = ret.length();
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
if (ret[i] == '\\')
|
||||
{
|
||||
ret[i] = '/';
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _checkPath()
|
||||
{
|
||||
if (s_resourcePath.empty())
|
||||
{
|
||||
WCHAR utf16Path[CC_MAX_PATH] = { 0 };
|
||||
GetModuleFileNameW(NULL, utf16Path, CC_MAX_PATH - 1);
|
||||
WCHAR *pUtf16ExePath = &(utf16Path[0]);
|
||||
|
||||
// We need only directory part without exe
|
||||
WCHAR *pUtf16DirEnd = wcsrchr(pUtf16ExePath, L'\\');
|
||||
|
||||
char utf8ExeDir[CC_MAX_PATH] = { 0 };
|
||||
int nNum = WideCharToMultiByte(CP_UTF8, 0, pUtf16ExePath, pUtf16DirEnd-pUtf16ExePath+1, utf8ExeDir, sizeof(utf8ExeDir), nullptr, nullptr);
|
||||
|
||||
s_resourcePath = convertPathFormatToUnixStyle(utf8ExeDir);
|
||||
}
|
||||
}
|
||||
|
||||
FileUtils* FileUtils::getInstance()
|
||||
{
|
||||
if (s_sharedFileUtils == nullptr)
|
||||
{
|
||||
s_sharedFileUtils = new FileUtilsWin32();
|
||||
if(!s_sharedFileUtils->init())
|
||||
{
|
||||
delete s_sharedFileUtils;
|
||||
s_sharedFileUtils = nullptr;
|
||||
CCLOG("ERROR: Could not init CCFileUtilsWin32");
|
||||
}
|
||||
}
|
||||
return s_sharedFileUtils;
|
||||
}
|
||||
|
||||
FileUtilsWin32::FileUtilsWin32()
|
||||
{
|
||||
}
|
||||
|
||||
bool FileUtilsWin32::init()
|
||||
{
|
||||
_checkPath();
|
||||
_defaultResRootPath = s_resourcePath;
|
||||
return FileUtils::init();
|
||||
}
|
||||
|
||||
bool FileUtilsWin32::isDirectoryExistInternal(const std::string& dirPath) const
|
||||
{
|
||||
unsigned long fAttrib = GetFileAttributes(StringUtf8ToWideChar(dirPath).c_str());
|
||||
if (fAttrib != INVALID_FILE_ATTRIBUTES &&
|
||||
(fAttrib & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string FileUtilsWin32::getSuitableFOpen(const std::string& filenameUtf8) const
|
||||
{
|
||||
return UTF8StringToMultiByte(filenameUtf8);
|
||||
}
|
||||
|
||||
long FileUtilsWin32::getFileSize(const std::string &filepath)
|
||||
{
|
||||
WIN32_FILE_ATTRIBUTE_DATA fad;
|
||||
if (!GetFileAttributesEx(StringUtf8ToWideChar(filepath).c_str(), GetFileExInfoStandard, &fad))
|
||||
{
|
||||
return 0; // error condition, could call GetLastError to find out more
|
||||
}
|
||||
LARGE_INTEGER size;
|
||||
size.HighPart = fad.nFileSizeHigh;
|
||||
size.LowPart = fad.nFileSizeLow;
|
||||
return (long)size.QuadPart;
|
||||
}
|
||||
|
||||
bool FileUtilsWin32::isFileExistInternal(const std::string& strFilePath) const
|
||||
{
|
||||
if (strFilePath.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string strPath = strFilePath;
|
||||
if (!isAbsolutePath(strPath))
|
||||
{ // Not absolute path, add the default root path at the beginning.
|
||||
strPath.insert(0, _defaultResRootPath);
|
||||
}
|
||||
|
||||
DWORD attr = GetFileAttributesW(StringUtf8ToWideChar(strPath).c_str());
|
||||
if(attr == INVALID_FILE_ATTRIBUTES || (attr & FILE_ATTRIBUTE_DIRECTORY))
|
||||
return false; // not a file
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileUtilsWin32::isAbsolutePath(const std::string& strPath) const
|
||||
{
|
||||
if ( (strPath.length() > 2
|
||||
&& ( (strPath[0] >= 'a' && strPath[0] <= 'z') || (strPath[0] >= 'A' && strPath[0] <= 'Z') )
|
||||
&& strPath[1] == ':') || (strPath[0] == '/' && strPath[1] == '/'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
FileUtils::Status FileUtilsWin32::getContents(const std::string& filename, ResizableBuffer* buffer)
|
||||
{
|
||||
if (filename.empty())
|
||||
return FileUtils::Status::NotExists;
|
||||
|
||||
// read the file from hardware
|
||||
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filename);
|
||||
|
||||
HANDLE fileHandle = ::CreateFile(StringUtf8ToWideChar(fullPath).c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, nullptr);
|
||||
if (fileHandle == INVALID_HANDLE_VALUE)
|
||||
return FileUtils::Status::OpenFailed;
|
||||
|
||||
DWORD hi;
|
||||
auto size = ::GetFileSize(fileHandle, &hi);
|
||||
if (hi > 0)
|
||||
{
|
||||
::CloseHandle(fileHandle);
|
||||
return FileUtils::Status::TooLarge;
|
||||
}
|
||||
// don't read file content if it is empty
|
||||
if (size == 0)
|
||||
{
|
||||
::CloseHandle(fileHandle);
|
||||
return FileUtils::Status::OK;
|
||||
}
|
||||
|
||||
buffer->resize(size);
|
||||
DWORD sizeRead = 0;
|
||||
BOOL successed = ::ReadFile(fileHandle, buffer->buffer(), size, &sizeRead, nullptr);
|
||||
::CloseHandle(fileHandle);
|
||||
|
||||
if (!successed) {
|
||||
CCLOG("Get data from file(%s) failed, error code is %s", filename.data(), std::to_string(::GetLastError()).data());
|
||||
buffer->resize(sizeRead);
|
||||
return FileUtils::Status::ReadFailed;
|
||||
}
|
||||
return FileUtils::Status::OK;
|
||||
}
|
||||
|
||||
std::string FileUtilsWin32::getPathForFilename(const std::string& filename, const std::string& resolutionDirectory, const std::string& searchPath) const
|
||||
{
|
||||
std::string unixFileName = convertPathFormatToUnixStyle(filename);
|
||||
std::string unixResolutionDirectory = convertPathFormatToUnixStyle(resolutionDirectory);
|
||||
std::string unixSearchPath = convertPathFormatToUnixStyle(searchPath);
|
||||
|
||||
return FileUtils::getPathForFilename(unixFileName, unixResolutionDirectory, unixSearchPath);
|
||||
}
|
||||
|
||||
std::string FileUtilsWin32::getFullPathForDirectoryAndFilename(const std::string& strDirectory, const std::string& strFilename) const
|
||||
{
|
||||
std::string unixDirectory = convertPathFormatToUnixStyle(strDirectory);
|
||||
std::string unixFilename = convertPathFormatToUnixStyle(strFilename);
|
||||
|
||||
return FileUtils::getFullPathForDirectoryAndFilename(unixDirectory, unixFilename);
|
||||
}
|
||||
|
||||
string FileUtilsWin32::getWritablePath() const
|
||||
{
|
||||
if (_writablePath.length())
|
||||
{
|
||||
return _writablePath;
|
||||
}
|
||||
|
||||
// Get full path of executable, e.g. c:\Program Files (x86)\My Game Folder\MyGame.exe
|
||||
WCHAR full_path[CC_MAX_PATH + 1] = { 0 };
|
||||
::GetModuleFileName(nullptr, full_path, CC_MAX_PATH + 1);
|
||||
|
||||
// Debug app uses executable directory; Non-debug app uses local app data directory
|
||||
//#ifndef _DEBUG
|
||||
// Get filename of executable only, e.g. MyGame.exe
|
||||
WCHAR *base_name = wcsrchr(full_path, '\\');
|
||||
wstring retPath;
|
||||
if(base_name)
|
||||
{
|
||||
WCHAR app_data_path[CC_MAX_PATH + 1];
|
||||
|
||||
// Get local app data directory, e.g. C:\Documents and Settings\username\Local Settings\Application Data
|
||||
if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_LOCAL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, app_data_path)))
|
||||
{
|
||||
wstring ret(app_data_path);
|
||||
|
||||
// Adding executable filename, e.g. C:\Documents and Settings\username\Local Settings\Application Data\MyGame.exe
|
||||
ret += base_name;
|
||||
|
||||
// Remove ".exe" extension, e.g. C:\Documents and Settings\username\Local Settings\Application Data\MyGame
|
||||
ret = ret.substr(0, ret.rfind(L"."));
|
||||
|
||||
ret += L"\\";
|
||||
|
||||
// Create directory
|
||||
if (SUCCEEDED(SHCreateDirectoryEx(nullptr, ret.c_str(), nullptr)))
|
||||
{
|
||||
retPath = ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (retPath.empty())
|
||||
//#endif // not defined _DEBUG
|
||||
{
|
||||
// If fetching of local app data directory fails, use the executable one
|
||||
retPath = full_path;
|
||||
|
||||
// remove xxx.exe
|
||||
retPath = retPath.substr(0, retPath.rfind(L"\\") + 1);
|
||||
}
|
||||
|
||||
return convertPathFormatToUnixStyle(StringWideCharToUtf8(retPath));
|
||||
}
|
||||
|
||||
bool FileUtilsWin32::renameFile(const std::string &oldfullpath, const std::string& newfullpath)
|
||||
{
|
||||
CCASSERT(!oldfullpath.empty(), "Invalid path");
|
||||
CCASSERT(!newfullpath.empty(), "Invalid path");
|
||||
|
||||
std::wstring _wNew = StringUtf8ToWideChar(newfullpath);
|
||||
std::wstring _wOld = StringUtf8ToWideChar(oldfullpath);
|
||||
|
||||
if (FileUtils::getInstance()->isFileExist(newfullpath))
|
||||
{
|
||||
if (!DeleteFile(_wNew.c_str()))
|
||||
{
|
||||
CCLOGERROR("Fail to delete file %s !Error code is 0x%x", newfullpath.c_str(), GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
if (MoveFile(_wOld.c_str(), _wNew.c_str()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOGERROR("Fail to rename file %s to %s !Error code is 0x%x", oldfullpath.c_str(), newfullpath.c_str(), GetLastError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileUtilsWin32::renameFile(const std::string &path, const std::string &oldname, const std::string &name)
|
||||
{
|
||||
CCASSERT(!path.empty(), "Invalid path");
|
||||
std::string oldPath = path + oldname;
|
||||
std::string newPath = path + name;
|
||||
|
||||
std::regex pat("\\/");
|
||||
std::string _old = std::regex_replace(oldPath, pat, "\\");
|
||||
std::string _new = std::regex_replace(newPath, pat, "\\");
|
||||
|
||||
return renameFile(_old, _new);
|
||||
}
|
||||
|
||||
bool FileUtilsWin32::createDirectory(const std::string& dirPath)
|
||||
{
|
||||
CCASSERT(!dirPath.empty(), "Invalid path");
|
||||
|
||||
if (isDirectoryExist(dirPath))
|
||||
return true;
|
||||
|
||||
std::wstring path = StringUtf8ToWideChar(dirPath);
|
||||
|
||||
// Split the path
|
||||
size_t start = 0;
|
||||
size_t found = path.find_first_of(L"/\\", start);
|
||||
std::wstring subpath;
|
||||
std::vector<std::wstring> dirs;
|
||||
|
||||
if (found != std::wstring::npos)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
subpath = path.substr(start, found - start + 1);
|
||||
if (!subpath.empty())
|
||||
dirs.push_back(subpath);
|
||||
start = found + 1;
|
||||
found = path.find_first_of(L"/\\", start);
|
||||
if (found == std::wstring::npos)
|
||||
{
|
||||
if (start < path.length())
|
||||
{
|
||||
dirs.push_back(path.substr(start));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((GetFileAttributes(path.c_str())) == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
subpath = L"";
|
||||
for (unsigned int i = 0; i < dirs.size(); ++i)
|
||||
{
|
||||
subpath += dirs[i];
|
||||
|
||||
std::string utf8Path = StringWideCharToUtf8(subpath);
|
||||
if (!isDirectoryExist(utf8Path))
|
||||
{
|
||||
BOOL ret = CreateDirectory(subpath.c_str(), NULL);
|
||||
if (!ret && ERROR_ALREADY_EXISTS != GetLastError())
|
||||
{
|
||||
CCLOGERROR("Fail create directory %s !Error code is 0x%x", utf8Path.c_str(), GetLastError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileUtilsWin32::removeFile(const std::string &filepath)
|
||||
{
|
||||
std::regex pat("\\/");
|
||||
std::string win32path = std::regex_replace(filepath, pat, "\\");
|
||||
|
||||
if (DeleteFile(StringUtf8ToWideChar(win32path).c_str()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOGERROR("Fail remove file %s !Error code is 0x%x", filepath.c_str(), GetLastError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileUtilsWin32::removeDirectory(const std::string& dirPath)
|
||||
{
|
||||
std::wstring wpath = StringUtf8ToWideChar(dirPath);
|
||||
std::wstring files = wpath + L"*.*";
|
||||
WIN32_FIND_DATA wfd;
|
||||
HANDLE search = FindFirstFileEx(files.c_str(), FindExInfoStandard, &wfd, FindExSearchNameMatch, NULL, 0);
|
||||
bool ret = true;
|
||||
if (search != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
BOOL find = true;
|
||||
while (find)
|
||||
{
|
||||
// Need check string . and .. for delete folders and files begin name.
|
||||
std::wstring fileName = wfd.cFileName;
|
||||
if (fileName != L"." && fileName != L"..")
|
||||
{
|
||||
std::wstring temp = wpath + wfd.cFileName;
|
||||
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
temp += '/';
|
||||
ret = ret && this->removeDirectory(StringWideCharToUtf8(temp));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFileAttributes(temp.c_str(), FILE_ATTRIBUTE_NORMAL);
|
||||
ret = ret && DeleteFile(temp.c_str());
|
||||
}
|
||||
}
|
||||
find = FindNextFile(search, &wfd);
|
||||
}
|
||||
FindClose(search);
|
||||
}
|
||||
if (ret && RemoveDirectory(wpath.c_str()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
144
cocos2d-x/cocos/platform/win32/CCFileUtils-win32.h
Normal file
144
cocos2d-x/cocos/platform/win32/CCFileUtils-win32.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#ifndef __CC_FILEUTILS_WIN32_H__
|
||||
#define __CC_FILEUTILS_WIN32_H__
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include "base/ccMacros.h"
|
||||
#include "base/ccTypes.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
/**
|
||||
* @addtogroup platform
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! @brief Helper class to handle file operations
|
||||
class CC_DLL FileUtilsWin32 : public FileUtils
|
||||
{
|
||||
friend class FileUtils;
|
||||
FileUtilsWin32();
|
||||
public:
|
||||
/* override functions */
|
||||
bool init();
|
||||
virtual std::string getWritablePath() const override;
|
||||
virtual bool isAbsolutePath(const std::string& strPath) const override;
|
||||
virtual std::string getSuitableFOpen(const std::string& filenameUtf8) const override;
|
||||
virtual long getFileSize(const std::string &filepath);
|
||||
protected:
|
||||
|
||||
virtual bool isFileExistInternal(const std::string& strFilePath) const override;
|
||||
|
||||
/**
|
||||
* Renames a file under the given directory.
|
||||
*
|
||||
* @param path The parent directory path of the file, it must be an absolute path.
|
||||
* @param oldname The current name of the file.
|
||||
* @param name The new name of the file.
|
||||
* @return True if the file have been renamed successfully, false if not.
|
||||
*/
|
||||
virtual bool renameFile(const std::string &path, const std::string &oldname, const std::string &name) override;
|
||||
|
||||
/**
|
||||
* Renames a file under the given directory.
|
||||
*
|
||||
* @param oldfullpath The current path + name of the file.
|
||||
* @param newfullpath The new path + name of the file.
|
||||
* @return True if the file have been renamed successfully, false if not.
|
||||
*/
|
||||
virtual bool renameFile(const std::string &oldfullpath, const std::string &newfullpath) override;
|
||||
|
||||
/**
|
||||
* Checks whether a directory exists without considering search paths and resolution orders.
|
||||
* @param dirPath The directory (with absolute path) to look up for
|
||||
* @return Returns true if the directory found at the given absolute path, otherwise returns false
|
||||
*/
|
||||
virtual bool isDirectoryExistInternal(const std::string& dirPath) const override;
|
||||
|
||||
/**
|
||||
* Removes a file.
|
||||
*
|
||||
* @param filepath The full path of the file, it must be an absolute path.
|
||||
* @return True if the file have been removed successfully, false if not.
|
||||
*/
|
||||
virtual bool removeFile(const std::string &filepath) override;
|
||||
|
||||
/**
|
||||
* Creates a directory.
|
||||
*
|
||||
* @param dirPath The path of the directory, it must be an absolute path.
|
||||
* @return True if the directory have been created successfully, false if not.
|
||||
*/
|
||||
virtual bool createDirectory(const std::string& dirPath) override;
|
||||
|
||||
/**
|
||||
* Removes a directory.
|
||||
*
|
||||
* @param dirPath The full path of the directory, it must be an absolute path.
|
||||
* @return True if the directory have been removed successfully, false if not.
|
||||
*/
|
||||
virtual bool removeDirectory(const std::string& dirPath) override;
|
||||
|
||||
|
||||
virtual FileUtils::Status getContents(const std::string& filename, ResizableBuffer* buffer) override;
|
||||
|
||||
/**
|
||||
* Gets full path for filename, resolution directory and search path.
|
||||
*
|
||||
* @param filename The file name.
|
||||
* @param resolutionDirectory The resolution directory.
|
||||
* @param searchPath The search path.
|
||||
* @return The full path of the file. It will return an empty string if the full path of the file doesn't exist.
|
||||
*/
|
||||
virtual std::string getPathForFilename(const std::string& filename, const std::string& resolutionDirectory, const std::string& searchPath) const override;
|
||||
|
||||
/**
|
||||
* Gets full path for the directory and the filename.
|
||||
*
|
||||
* @note Only iOS and Mac need to override this method since they are using
|
||||
* `[[NSBundle mainBundle] pathForResource: ofType: inDirectory:]` to make a full path.
|
||||
* Other platforms will use the default implementation of this method.
|
||||
* @param directory The directory contains the file we are looking for.
|
||||
* @param filename The name of the file.
|
||||
* @return The full path of the file, if the file can't be found, it will return an empty string.
|
||||
*/
|
||||
virtual std::string getFullPathForDirectoryAndFilename(const std::string& directory, const std::string& filename) const override;
|
||||
};
|
||||
|
||||
// end of platform group
|
||||
/// @}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
||||
#endif // __CC_FILEUTILS_WIN32_H__
|
||||
39
cocos2d-x/cocos/platform/win32/CCGL-win32.h
Normal file
39
cocos2d-x/cocos/platform/win32/CCGL-win32.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __CCGL_H__
|
||||
#define __CCGL_H__
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
||||
#include "gles/glew.h"
|
||||
|
||||
#define CC_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
||||
#endif // __CCGL_H__
|
||||
79
cocos2d-x/cocos/platform/win32/CCPlatformDefine-win32.h
Normal file
79
cocos2d-x/cocos/platform/win32/CCPlatformDefine-win32.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#ifndef __CCPLATFORMDEFINE_H__
|
||||
#define __CCPLATFORMDEFINE_H__
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#if defined(CC_STATIC)
|
||||
#define CC_DLL
|
||||
#else
|
||||
#if defined(_USRDLL)
|
||||
#define CC_DLL __declspec(dllexport)
|
||||
#else /* use a DLL library */
|
||||
#define CC_DLL __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#if CC_DISABLE_ASSERT > 0
|
||||
#define CC_ASSERT(cond)
|
||||
#else
|
||||
#define CC_ASSERT(cond) assert(cond)
|
||||
#endif
|
||||
#define CC_UNUSED_PARAM(unusedparam) (void)unusedparam
|
||||
|
||||
/* Define NULL pointer value */
|
||||
#ifndef NULL
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if _MSC_VER > 1800
|
||||
#pragma comment(lib,"libpng-2015.lib")
|
||||
#pragma comment(lib,"libjpeg-2015.lib")
|
||||
#pragma comment(lib,"libtiff-2015.lib")
|
||||
#pragma comment(lib,"glfw3-2015.lib")
|
||||
#else
|
||||
#pragma comment(lib,"libpng.lib")
|
||||
#pragma comment(lib,"libjpeg.lib")
|
||||
#pragma comment(lib,"libtiff.lib")
|
||||
#pragma comment(lib,"glfw3.lib")
|
||||
#endif
|
||||
|
||||
#endif //s CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
||||
#endif /* __CCPLATFORMDEFINE_H__*/
|
||||
|
||||
55
cocos2d-x/cocos/platform/win32/CCStdC-win32.cpp
Normal file
55
cocos2d-x/cocos/platform/win32/CCStdC-win32.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
||||
#include "platform/CCStdC.h"
|
||||
|
||||
#ifndef __MINGW32__
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
int gettimeofday(struct timeval * val, struct timezone *)
|
||||
{
|
||||
if (val)
|
||||
{
|
||||
LARGE_INTEGER liTime, liFreq;
|
||||
QueryPerformanceFrequency( &liFreq );
|
||||
QueryPerformanceCounter( &liTime );
|
||||
val->tv_sec = (long)( liTime.QuadPart / liFreq.QuadPart );
|
||||
val->tv_usec = (long)( liTime.QuadPart * 1000000.0 / liFreq.QuadPart - val->tv_sec * 1000000.0 );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // __MINGW32__
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
||||
98
cocos2d-x/cocos/platform/win32/CCStdC-win32.h
Normal file
98
cocos2d-x/cocos/platform/win32/CCStdC-win32.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <BaseTsd.h>
|
||||
#ifndef __SSIZE_T
|
||||
#define __SSIZE_T
|
||||
typedef SSIZE_T ssize_t;
|
||||
#endif // __SSIZE_T
|
||||
|
||||
#include <float.h>
|
||||
|
||||
|
||||
|
||||
// for math.h on win32 platform
|
||||
#ifndef __MINGW32__
|
||||
|
||||
#if !defined(_USE_MATH_DEFINES)
|
||||
#define _USE_MATH_DEFINES // make M_PI can be use
|
||||
#endif
|
||||
|
||||
#if _MSC_VER < 1800
|
||||
#if !defined(isnan)
|
||||
#define isnan _isnan
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if _MSC_VER < 1900
|
||||
#ifndef snprintf
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // __MINGW32__
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358
|
||||
#endif
|
||||
#ifndef M_PI_2
|
||||
#define M_PI_2 1.57079632679
|
||||
#endif
|
||||
// for MIN MAX and sys/time.h on win32 platform
|
||||
|
||||
|
||||
#if _MSC_VER >= 1600 || defined(__MINGW32__)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include "platform/win32/compat/stdint.h"
|
||||
#endif
|
||||
|
||||
|
||||
// Conflicted with ParticleSystem::PositionType::RELATIVE, so we need to undef it.
|
||||
#ifdef RELATIVE
|
||||
#undef RELATIVE
|
||||
#endif
|
||||
|
||||
// Conflicted with CCBReader::SizeType::RELATIVE and CCBReader::ScaleType::RELATIVE, so we need to undef it.
|
||||
#ifdef ABSOLUTE
|
||||
#undef ABSOLUTE
|
||||
#endif
|
||||
|
||||
// Conflicted with HttpRequest::Type::DELETE, so we need to undef it.
|
||||
#ifdef DELETE
|
||||
#undef DELETE
|
||||
#endif
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
108
cocos2d-x/cocos/platform/win32/CCUtils-win32.cpp
Normal file
108
cocos2d-x/cocos/platform/win32/CCUtils-win32.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "platform/win32/CCUtils-win32.h"
|
||||
#include "platform/CCStdC.h"
|
||||
#include <sstream>
|
||||
#include "base/ccMacros.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
std::wstring StringUtf8ToWideChar(const std::string& strUtf8)
|
||||
{
|
||||
std::wstring ret;
|
||||
if (!strUtf8.empty())
|
||||
{
|
||||
int nNum = MultiByteToWideChar(CP_UTF8, 0, strUtf8.c_str(), -1, nullptr, 0);
|
||||
if (nNum)
|
||||
{
|
||||
WCHAR* wideCharString = new WCHAR[nNum + 1];
|
||||
wideCharString[0] = 0;
|
||||
|
||||
nNum = MultiByteToWideChar(CP_UTF8, 0, strUtf8.c_str(), -1, wideCharString, nNum + 1);
|
||||
|
||||
ret = wideCharString;
|
||||
delete[] wideCharString;
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOG("Wrong convert to WideChar code:0x%x", GetLastError());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string StringWideCharToUtf8(const std::wstring& strWideChar)
|
||||
{
|
||||
std::string ret;
|
||||
if (!strWideChar.empty())
|
||||
{
|
||||
int nNum = WideCharToMultiByte(CP_UTF8, 0, strWideChar.c_str(), -1, nullptr, 0, nullptr, FALSE);
|
||||
if (nNum)
|
||||
{
|
||||
char* utf8String = new char[nNum + 1];
|
||||
utf8String[0] = 0;
|
||||
|
||||
nNum = WideCharToMultiByte(CP_UTF8, 0, strWideChar.c_str(), -1, utf8String, nNum + 1, nullptr, FALSE);
|
||||
|
||||
ret = utf8String;
|
||||
delete[] utf8String;
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOG("Wrong convert to Utf8 code:0x%x", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string UTF8StringToMultiByte(const std::string& strUtf8)
|
||||
{
|
||||
std::string ret;
|
||||
if (!strUtf8.empty())
|
||||
{
|
||||
std::wstring strWideChar = StringUtf8ToWideChar(strUtf8);
|
||||
int nNum = WideCharToMultiByte(CP_ACP, 0, strWideChar.c_str(), -1, nullptr, 0, nullptr, FALSE);
|
||||
if (nNum)
|
||||
{
|
||||
char* ansiString = new char[nNum + 1];
|
||||
ansiString[0] = 0;
|
||||
|
||||
nNum = WideCharToMultiByte(CP_ACP, 0, strWideChar.c_str(), -1, ansiString, nNum + 1, nullptr, FALSE);
|
||||
|
||||
ret = ansiString;
|
||||
delete[] ansiString;
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOG("Wrong convert to Ansi code:0x%x", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
42
cocos2d-x/cocos/platform/win32/CCUtils-win32.h
Normal file
42
cocos2d-x/cocos/platform/win32/CCUtils-win32.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __CC_UTILS_WIN32_H__
|
||||
#define __CC_UTILS_WIN32_H__
|
||||
|
||||
#include "base/ccMacros.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
std::wstring CC_DLL StringUtf8ToWideChar(const std::string& strUtf8);
|
||||
std::string CC_DLL StringWideCharToUtf8(const std::wstring& strWideChar);
|
||||
std::string CC_DLL UTF8StringToMultiByte(const std::string& strUtf8);
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // __CC_UTILS_WIN32_H__
|
||||
251
cocos2d-x/cocos/platform/win32/compat/stdint.h
Normal file
251
cocos2d-x/cocos/platform/win32/compat/stdint.h
Normal file
@@ -0,0 +1,251 @@
|
||||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2008 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
|
||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
// realize that, e.g. char has the same size as __int8
|
||||
// so we give up on __intX for them.
|
||||
#if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user