初始化

This commit is contained in:
SmallMain
2022-06-25 00:23:03 +08:00
commit ef0589e8e5
2264 changed files with 617829 additions and 0 deletions

View 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

View 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

View 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__ */

File diff suppressed because it is too large Load Diff

View 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__

View 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__*/

File diff suppressed because it is too large Load Diff

View 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__

View 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__

View 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__*/

View 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

View 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__

View 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

View 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)

View 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

View File

@@ -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

View 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

View 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

View 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__

View 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__

View 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__*/

View 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>

View 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>

View File

@@ -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>

View 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>

View 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 *;
#}

View File

View 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;
}
}

View File

@@ -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
// ===========================================================
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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());
}
}

View File

@@ -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;
}
}
}

View File

@@ -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};
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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
// ===========================================================
}

View File

@@ -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
// ===========================================================
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View 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);
}
}

View File

@@ -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);
}
}
});
}
}

View File

@@ -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);
}
}
}

View 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

View 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__

View 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, &copy);
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;
}

View 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();

View File

@@ -0,0 +1,7 @@
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures

View File

@@ -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>

View 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')
}

View 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 *;
#}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View 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 */

View 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

View 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__

View 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

View 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;

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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

View File

@@ -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

View 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__*/

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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

View File

@@ -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

View 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__*/

View 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

View 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

View File

@@ -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

View 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

View 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

View 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__

View 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__

View 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__*/

View 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

View 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

View 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

View 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__

View 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