Run NinjaSnowWar by default on Android.
Rudimentary touch controls (virtual on-screen joystick) in NinjaSnowWar.
Improved OpenGL ES depth bias.
Support GetUserDocumentsDir() on Android (return the getFilesDir() path.)
Fixed OpenGL ES mode erroneously attempting to use shadowed point lights.
Added .bat file to copy Data & CoreData directories as Android assets.
This commit is contained in:
Lasse Öörni 2012-05-27 00:27:23 +00:00
Родитель 4d317ebdef
Коммит 0706ae397f
32 изменённых файлов: 1304 добавлений и 849 удалений

Просмотреть файл

@ -3,7 +3,7 @@
package="org.libsdl.app"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-sdk android:targetSdkVersion="8" android:minSdkVersion="8" />
<application android:label="@string/app_name" android:icon="@drawable/icon">

4
Android/CopyData.bat Normal file
Просмотреть файл

@ -0,0 +1,4 @@
md assets\Data
xcopy ..\Bin\Data\*.* assets\Data /S /E /C /Y
md assets\CoreData
xcopy ..\Bin\CoreData\*.* assets\CoreData /S /E /C /Y

Просмотреть файл

@ -1,4 +1,4 @@
// Modified by Lasse Öörni for Urho3D
// Modified by Lasse Oorni for Urho3D
package org.libsdl.app;
@ -82,8 +82,8 @@ public class SDLActivity extends Activity {
}
protected void onDestroy() {
super.onDestroy();
Log.v("SDL", "onDestroy()");
super.onDestroy();
mFinished = true;
@ -109,6 +109,10 @@ public class SDLActivity extends Activity {
super.onConfigurationChanged(newConfig);
}
public static SDLActivity getSingleton() {
return mSingleton;
}
// Messages from the SDLMain thread
static int COMMAND_CHANGE_TITLE = 1;
static int COMMAND_FINISH = 2;
@ -137,7 +141,7 @@ public class SDLActivity extends Activity {
}
// C functions we call
public static native void nativeInit();
public static native void nativeInit(String filesDir);
public static native void nativeQuit();
public static native void nativePause();
public static native void nativeResume();
@ -145,7 +149,7 @@ public class SDLActivity extends Activity {
public static native void onNativeKeyDown(int keycode);
public static native void onNativeKeyUp(int keycode);
public static native void onNativeTouch(int touchDevId, int pointerFingerId,
int action, float x,
int action, float x,
float y, float p);
public static native void onNativeAccel(float x, float y, float z);
public static native void nativeRunAudioThread();
@ -165,7 +169,7 @@ public class SDLActivity extends Activity {
// Called from SDLMain() thread and can't directly affect the view
mSingleton.sendCommand(COMMAND_CHANGE_TITLE, title);
}
public static void finishActivity() {
mSingleton.sendCommand(COMMAND_FINISH, null);
}
@ -310,34 +314,34 @@ public class SDLActivity extends Activity {
// Audio
private static Object buf;
public static Object audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) {
int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT;
int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1);
Log.v("SDL", "SDL audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + ((float)sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer");
// Let the user pick a larger buffer if they really want -- but ye
// gods they probably shouldn't, the minimums are horrifyingly high
// latency already
desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
audioStartThread();
Log.v("SDL", "SDL audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer");
if (is16Bit) {
buf = new short[desiredFrames * (isStereo ? 2 : 1)];
} else {
buf = new byte[desiredFrames * (isStereo ? 2 : 1)];
buf = new byte[desiredFrames * (isStereo ? 2 : 1)];
}
return buf;
}
public static void audioStartThread() {
mAudioThread = new Thread(new Runnable() {
public void run() {
@ -345,12 +349,12 @@ public class SDLActivity extends Activity {
nativeRunAudioThread();
}
});
// I'd take REALTIME if I could get it!
mAudioThread.setPriority(Thread.MAX_PRIORITY);
mAudioThread.start();
}
public static void audioWriteShortBuffer(short[] buffer) {
for (int i = 0; i < buffer.length; ) {
int result = mAudioTrack.write(buffer, i, buffer.length - i);
@ -368,7 +372,7 @@ public class SDLActivity extends Activity {
}
}
}
public static void audioWriteByteBuffer(byte[] buffer) {
for (int i = 0; i < buffer.length; ) {
int result = mAudioTrack.write(buffer, i, buffer.length - i);
@ -412,7 +416,7 @@ public class SDLActivity extends Activity {
class SDLMain implements Runnable {
public void run() {
// Runs SDL_main()
SDLActivity.nativeInit();
SDLActivity.nativeInit(SDLActivity.getSingleton().getFilesDir().getAbsolutePath());
//Log.v("SDL", "SDL thread terminated");
SDLActivity.finishActivity();
@ -436,14 +440,14 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
public SDLSurface(Context context) {
super(context);
getHolder().addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
setOnKeyListener(this);
setOnTouchListener(this);
setOnKeyListener(this);
setOnTouchListener(this);
mSensorManager = (SensorManager)context.getSystemService("sensor");
mSensorManager = (SensorManager)context.getSystemService("sensor");
}
// Called when we have a valid drawing surface
@ -525,6 +529,10 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
// Key events
public boolean onKey(View v, int keyCode, KeyEvent event) {
// Urho3D: let the home & volume keys be handled by the system
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_HOME)
return false;
if (event.getAction() == KeyEvent.ACTION_DOWN) {
//Log.v("SDL", "key down: " + keyCode);
SDLActivity.onNativeKeyDown(keyCode);
@ -535,7 +543,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
SDLActivity.onNativeKeyUp(keyCode);
return true;
}
return false;
}
@ -568,21 +576,21 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
}
}
return true;
}
}
// Sensor events
public void enableSensor(int sensortype, boolean enabled) {
// TODO: This uses getDefaultSensor - what if we have >1 accels?
if (enabled) {
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(sensortype),
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(sensortype),
SensorManager.SENSOR_DELAY_GAME, null);
} else {
mSensorManager.unregisterListener(this,
mSensorManager.unregisterListener(this,
mSensorManager.getDefaultSensor(sensortype));
}
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO
}

Просмотреть файл

@ -41,6 +41,8 @@ void CreateCursor()
cursor.style = uiStyle;
cursor.SetPosition(graphics.width / 2, graphics.height / 2);
ui.cursor = cursor;
if (GetPlatform() == "Android")
ui.cursor.visible = false;
}
void CreateMenuBar()

Просмотреть файл

@ -9,6 +9,7 @@
#include "Scripts/Utilities/Network.as"
const float mouseSensitivity = 0.125;
const float touchSensitivity = 2.0;
const float cameraMinDist = 25;
const float cameraMaxDist = 500;
const float cameraSafetyDist = 30;
@ -29,6 +30,8 @@ Text@ hiscoreText;
Text@ messageText;
BorderImage@ healthBar;
BorderImage@ sight;
BorderImage@ moveButton;
BorderImage@ shootButton;
SoundSource@ musicSource;
Controls playerControls;
@ -44,6 +47,12 @@ float powerupSpawnTimer = 0;
uint clientNodeID = 0;
int clientScore = 0;
bool touchEnabled = false;
int touchButtonSize = 96;
int moveTouchID = -1;
int rotateTouchID = -1;
int fireTouchID = -1;
Array<Player> players;
Array<HiscoreEntry> hiscores;
@ -73,6 +82,8 @@ void Start()
SubscribeToEvent("Kill", "HandleKill");
SubscribeToEvent("ScreenMode", "HandleScreenMode");
if (touchEnabled)
SubscribeToEvent("TouchEnd", "HandleTouchEnd");
if (singlePlayer)
StartGame(null);
}
@ -225,6 +236,25 @@ void CreateOverlays()
healthBar.SetPosition(2, 2);
healthBar.SetSize(116, 16);
healthBorder.AddChild(healthBar);
if (GetPlatform() == "Android")
{
touchEnabled = true;
moveButton = BorderImage();
moveButton.texture = cache.GetResource("Texture2D", "Textures/TouchInput.png");
moveButton.imageRect = IntRect(0, 0, 96, 96);
moveButton.SetPosition(0, graphics.height - touchButtonSize);
moveButton.SetSize(touchButtonSize, touchButtonSize);
ui.root.AddChild(moveButton);
shootButton = BorderImage();
shootButton.texture = cache.GetResource("Texture2D", "Textures/TouchInput.png");
shootButton.imageRect = IntRect(96, 0, 192, 96);
shootButton.SetPosition(graphics.width - touchButtonSize, graphics.height - touchButtonSize);
shootButton.SetSize(touchButtonSize, touchButtonSize);
ui.root.AddChild(shootButton);
}
}
void SetMessage(const String&in message)
@ -374,6 +404,17 @@ void HandlePostRenderUpdate()
gameScene.octree.DrawDebugGeometry(true);
}
void HandleTouchEnd(StringHash eventType, VariantMap& eventData)
{
int touchID = eventData["TouchID"].GetInt();
if (touchID == moveTouchID)
moveTouchID = -1;
if (touchID == rotateTouchID)
rotateTouchID = -1;
if (touchID == fireTouchID)
fireTouchID = -1;
}
void HandleKeyDown(StringHash eventType, VariantMap& eventData)
{
int key = eventData["Key"].GetInt();
@ -724,6 +765,41 @@ void UpdateControls()
prevPlayerControls = playerControls;
playerControls.Set(CTRL_ALL, false);
if (touchEnabled)
{
for (int i = 0; i < input.numTouches; ++i)
{
TouchState touch = input.touches[i];
if (touch.touchID == rotateTouchID || (touch.position.y < graphics.height - touchButtonSize ||
(touch.position.x >= touchButtonSize && touch.position.x < graphics.width - touchButtonSize)))
{
rotateTouchID = touch.touchID;
playerControls.yaw += touchSensitivity * gameCamera.fov / graphics.height * touch.delta.x;
playerControls.pitch += touchSensitivity * gameCamera.fov / graphics.height * touch.delta.y;
}
else if (touch.position.y >= graphics.height - touchButtonSize && touch.position.x < touchButtonSize)
{
moveTouchID = touch.touchID;
int relX = touch.position.x - touchButtonSize / 2;
int relY = touch.position.y - (graphics.height - touchButtonSize / 2);
if (relY < 0 && Abs(relX * 3 / 2) < Abs(relY))
playerControls.Set(CTRL_UP, true);
if (relY > 0 && Abs(relX * 3 / 2) < Abs(relY))
playerControls.Set(CTRL_DOWN, true);
if (relX < 0 && Abs(relY * 3 / 2) < Abs(relX))
playerControls.Set(CTRL_LEFT, true);
if (relX > 0 && Abs(relY * 3 / 2) < Abs(relX))
playerControls.Set(CTRL_RIGHT, true);
}
else if (touch.position.y >= graphics.height - touchButtonSize && touch.position.x >= graphics.width -
touchButtonSize)
{
fireTouchID = touch.touchID;
playerControls.Set(CTRL_FIRE, true);
}
}
}
// For the triggered actions (fire & jump) check also for press, in case the FPS is low
// and the key was already released
if ((console is null) || (!console.visible))

Просмотреть файл

@ -83,7 +83,9 @@ void InitUI()
newCursor.style = uiStyle;
newCursor.position = IntVector2(graphics.width / 2, graphics.height / 2);
ui.cursor = newCursor;
if (GetPlatform() == "Android")
ui.cursor.visible = false;
downloadsText = Text();
downloadsText.SetAlignment(HA_CENTER, VA_CENTER);
downloadsText.SetFont(cache.GetResource("Font", "Fonts/Anonymous Pro.ttf"), 20);

Просмотреть файл

@ -289,6 +289,8 @@ void InitUI()
cursor.style = uiStyle;
cursor.position = IntVector2(graphics.width / 2, graphics.height / 2);
ui.cursor = cursor;
if (GetPlatform() == "Android")
ui.cursor.visible = false;
}
void CreateCamera()

Двоичные данные
Bin/Data/Textures/TouchInput.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.9 KiB

Просмотреть файл

@ -54,7 +54,7 @@ Urho3D.exe <scriptfilename> [options]
The scripting language used is AngelScript (http://www.angelcode.com/angelscript); the script files have .as extension and need to be placed under either the Data or CoreData subdirectories so that Urho3D.exe can find them. An application script is required to have the function void Start(), which will be executed before starting the engine main loop. It is this function's responsibility to initialize the application and to hook up to any necessary \ref Events "events", such as the update that happens every frame.
On Android there are no command line options, so the Urho3D activity chooses to load the TestScene example. This can be changed from Urho3D.cpp.
On Android there are no command line options, so running the NinjaSnowWar example is hardcoded. This can be changed from Urho3D.cpp.
Currently, five example application scripts exist:

Просмотреть файл

@ -2368,6 +2368,15 @@ Properties:<br>
- uint[] numOccluders (readonly)
TouchState
Properties:<br>
- int touchID
- IntVector2 position
- IntVector2 delta
- int pressure
Input
Properties:<br>
@ -2385,6 +2394,8 @@ Properties:<br>
- int mouseMoveX (readonly)
- int mouseMoveY (readonly)
- int mouseMoveWheel (readonly)
- uint numTouches (readonly)
- TouchState[] touches (readonly)
- bool active (readonly)
- bool minimized (readonly)

Просмотреть файл

@ -108,8 +108,20 @@ static Input* GetInput()
return GetScriptContext()->GetSubsystem<Input>();
}
static void ConstructTouchState(TouchState* ptr)
{
new(ptr) TouchState();
}
static void RegisterInput(asIScriptEngine* engine)
{
engine->RegisterObjectType("TouchState", sizeof(TouchState), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS);
engine->RegisterObjectBehaviour("TouchState", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructTouchState), asCALL_CDECL_OBJLAST);
engine->RegisterObjectProperty("TouchState", "int touchID", offsetof(TouchState, touchID_));
engine->RegisterObjectProperty("TouchState", "IntVector2 position", offsetof(TouchState, position_));
engine->RegisterObjectProperty("TouchState", "IntVector2 delta", offsetof(TouchState, delta_));
engine->RegisterObjectProperty("TouchState", "int pressure", offsetof(TouchState, pressure_));
RegisterObject<Input>(engine, "Input");
engine->RegisterObjectMethod("Input", "void set_toggleFullscreen(bool)", asMETHOD(Input, SetToggleFullscreen), asCALL_THISCALL);
engine->RegisterObjectMethod("Input", "bool get_toggleFullscreen() const", asMETHOD(Input, GetToggleFullscreen), asCALL_THISCALL);
@ -124,6 +136,8 @@ static void RegisterInput(asIScriptEngine* engine)
engine->RegisterObjectMethod("Input", "int get_mouseMoveX() const", asMETHOD(Input, GetMouseMoveX), asCALL_THISCALL);
engine->RegisterObjectMethod("Input", "int get_mouseMoveY() const", asMETHOD(Input, GetMouseMoveY), asCALL_THISCALL);
engine->RegisterObjectMethod("Input", "int get_mouseMoveWheel() const", asMETHOD(Input, GetMouseMoveWheel), asCALL_THISCALL);
engine->RegisterObjectMethod("Input", "uint get_numTouches() const", asMETHOD(Input, GetNumTouches), asCALL_THISCALL);
engine->RegisterObjectMethod("Input", "TouchState get_touches(uint) const", asMETHOD(Input, GetTouch), asCALL_THISCALL);
engine->RegisterObjectMethod("Input", "bool get_active() const", asMETHOD(Input, IsActive), asCALL_THISCALL);
engine->RegisterObjectMethod("Input", "bool get_minimized() const", asMETHOD(Input, IsMinimized), asCALL_THISCALL);
engine->RegisterGlobalFunction("Input@+ get_input()", asFUNCTION(GetInput), asCALL_CDECL);

Просмотреть файл

@ -1414,9 +1414,14 @@ void Graphics::SetDepthBias(float constantBias, float slopeScaledBias)
{
// Bring the constant bias from Direct3D9 scale to OpenGL (depends on depth buffer bitdepth)
// Zero depth bits may be returned if using the packed depth-stencil format. Assume 24bit in that case
#ifndef GL_ES_VERSION_2_0
int depthBits = Min(impl_->depthBits_, 23);
if (!depthBits)
depthBits = 23;
#else
int depthBits = 25;
#endif
float adjustedConstantBias = constantBias * (float)(1 << (depthBits - 1));
float adjustedSlopeScaledBias = slopeScaledBias + 1.0f;

Просмотреть файл

@ -26,6 +26,7 @@
#include "DebugRenderer.h"
#include "Geometry.h"
#include "Graphics.h"
#include "GraphicsImpl.h"
#include "Light.h"
#include "Log.h"
#include "OcclusionBuffer.h"

Просмотреть файл

@ -50,6 +50,10 @@
#include <mach-o/dyld.h>
#endif
#ifdef ANDROID
extern "C" const char* SDL_Android_GetFilesDir();
#endif
#include "DebugNew.h"
OBJECTTYPESTATIC(FileSystem);
@ -398,11 +402,13 @@ String FileSystem::GetProgramDir()
String FileSystem::GetUserDocumentsDir()
{
#ifdef WIN32
#if defined(WIN32)
wchar_t pathName[MAX_PATH];
pathName[0] = 0;
SHGetSpecialFolderPathW(0, pathName, CSIDL_PERSONAL, 0);
return AddTrailingSlash(String(pathName));
#elif defined(ANDROID)
return AddTrailingSlash(String(SDL_Android_GetFilesDir()));
#else
char pathName[MAX_PATH];
pathName[0] = 0;

Просмотреть файл

@ -169,6 +169,13 @@ void Input::Update()
mouseMove_ = IntVector2::ZERO;
mouseMoveWheel_ = 0;
// Reset touch delta movement. Note: last coordinates are stored internally, but the frame delta is returned to user
for (Map<int, TouchState>::Iterator i = touches_.Begin(); i != touches_.End(); ++i)
{
TouchState& state = i->second_;
state.delta_ = state.position_;
}
#ifndef USE_OPENGL
// Pump Win32 events
MSG msg;
@ -312,6 +319,25 @@ int Input::GetQualifiers() const
return ret;
}
TouchState Input::GetTouch(unsigned index) const
{
unsigned cmpIndex = 0;
for (Map<int, TouchState>::ConstIterator i = touches_.Begin(); i != touches_.End(); ++i)
{
if (cmpIndex == index)
{
TouchState ret = i->second_;
// Convert last position to delta
ret.delta_ = ret.position_ - ret.delta_;
return ret;
}
else
++cmpIndex;
}
return TouchState();
}
void Input::Initialize()
{
Graphics* graphics = GetSubsystem<Graphics>();
@ -397,6 +423,21 @@ void Input::ResetState()
keyDown_.Clear();
keyPress_.Clear();
// When clearing touch states, send the corresponding touch end events
for (Map<int, TouchState>::Iterator i = touches_.Begin(); i != touches_.End(); ++i)
{
TouchState& state = i->second_;
using namespace TouchEnd;
VariantMap eventData;
eventData[P_TOUCHID] = state.touchID_;
eventData[P_X] = state.position_.x_;
eventData[P_Y] = state.position_.y_;
SendEvent(E_TOUCHEND, eventData);
}
// Use SetMouseButton() to reset the state so that mouse events will be sent properly
SetMouseButton(MOUSEB_LEFT, false);
SetMouseButton(MOUSEB_RIGHT, false);
@ -733,6 +774,72 @@ void Input::HandleSDLEvent(void* sdlEvent)
input->SetMouseWheel(evt.wheel.y);
break;
case SDL_FINGERDOWN:
input = GetInputInstance(evt.tfinger.windowID);
if (input)
{
int touchID = (int)evt.tfinger.fingerId;
TouchState& state = input->touches_[touchID];
state.touchID_ = touchID;
state.delta_ = state.position_ = IntVector2(evt.tfinger.x * input->graphics_->GetWidth() / 32768,
evt.tfinger.y * input->graphics_->GetHeight() / 32768);
state.pressure_ = evt.tfinger.pressure;
using namespace TouchBegin;
VariantMap eventData;
eventData[P_TOUCHID] = touchID;
eventData[P_X] = state.position_.x_;
eventData[P_Y] = state.position_.y_;
eventData[P_PRESSURE] = state.pressure_;
input->SendEvent(E_TOUCHBEGIN, eventData);
}
break;
case SDL_FINGERUP:
input = GetInputInstance(evt.tfinger.windowID);
if (input)
{
int touchID = (int)evt.tfinger.fingerId;
input->touches_.Erase(touchID);
using namespace TouchEnd;
VariantMap eventData;
eventData[P_TOUCHID] = touchID;
eventData[P_X] = evt.tfinger.x * input->graphics_->GetWidth() / 32768;
eventData[P_Y] = evt.tfinger.y * input->graphics_->GetHeight() / 32768;
input->SendEvent(E_TOUCHEND, eventData);
}
break;
case SDL_FINGERMOTION:
input = GetInputInstance(evt.tfinger.windowID);
if (input)
{
int touchID = (int)evt.tfinger.fingerId;
TouchState& state = input->touches_[touchID];
state.touchID_ = touchID;
state.position_ = IntVector2(evt.tfinger.x * input->graphics_->GetWidth() / 32768,
evt.tfinger.y * input->graphics_->GetHeight() / 32768);
state.pressure_ = evt.tfinger.pressure;
using namespace TouchMove;
VariantMap eventData;
eventData[P_TOUCHID] = touchID;
eventData[P_X] = state.position_.x_;
eventData[P_Y] = state.position_.y_;
eventData[P_DX] = evt.tfinger.dx * input->graphics_->GetWidth() / 32768;
eventData[P_DY] = evt.tfinger.dy * input->graphics_->GetHeight() / 32768;
eventData[P_PRESSURE] = state.pressure_;
input->SendEvent(E_TOUCHMOVE, eventData);
}
break;
case SDL_WINDOWEVENT:
if (evt.window.event == SDL_WINDOWEVENT_CLOSE)
{

Просмотреть файл

@ -23,12 +23,26 @@
#pragma once
#include "Map.h"
#include "HashSet.h"
#include "InputEvents.h"
#include "Object.h"
class Graphics;
/// Structure for an ongoing finger touch.
struct TouchState
{
/// Touch (finger) ID.
int touchID_;
/// Position in screen coordinates.
IntVector2 position_;
/// Movement since last frame.
IntVector2 delta_;
/// Finger pressure.
int pressure_;
};
/// %Input subsystem. Converts operating system window messages to input state and events.
class Input : public Object
{
@ -67,6 +81,10 @@ public:
int GetMouseMoveY() const { return mouseMove_.y_; }
/// Return mouse wheel movement since last frame.
int GetMouseMoveWheel() const { return mouseMoveWheel_; }
/// Return number of active finger touches.
unsigned GetNumTouches() const { return touches_.Size(); }
/// Return active finger touch by index.
TouchState GetTouch(unsigned index) const;
/// Return whether fullscreen toggle is enabled.
bool GetToggleFullscreen() const { return toggleFullscreen_; }
/// Return whether application window is active.
@ -117,6 +135,8 @@ private:
HashSet<int> keyDown_;
/// Key pressed state.
HashSet<int> keyPress_;
/// Active finger touches.
Map<int, TouchState> touches_;
/// Mouse buttons' down state.
unsigned mouseButtonDown_;
/// Mouse buttons' pressed state.

Просмотреть файл

@ -87,6 +87,34 @@ EVENT(E_CHAR, Char)
PARAM(P_QUALIFIERS, Qualifiers); // int
}
/// Finger pressed on the screen.
EVENT(E_TOUCHBEGIN, TouchBegin)
{
PARAM(P_TOUCHID, TouchID); // int
PARAM(P_X, X); // int
PARAM(P_Y, Y); // int
PARAM(P_PRESSURE, Pressure); // int
}
/// Finger released from the screen.
EVENT(E_TOUCHEND, TouchEnd)
{
PARAM(P_TOUCHID, TouchID); // int
PARAM(P_X, X); // int
PARAM(P_Y, Y); // int
}
/// Finger moved on the screen.
EVENT(E_TOUCHMOVE, TouchMove)
{
PARAM(P_TOUCHID, TouchID); // int
PARAM(P_X, X); // int
PARAM(P_Y, Y); // int
PARAM(P_DX, DX); // int
PARAM(P_DY, DY); // int
PARAM(P_PRESSURE, Pressure); // int
}
/// Application activation state changed.
EVENT(E_ACTIVATION, Activation)
{

Просмотреть файл

@ -38,7 +38,7 @@ LineEdit::LineEdit(Context* context) :
lastFont_(0),
lastFontSize_(0),
cursorPosition_(0),
dragStartCursor_(M_MAX_UNSIGNED),
dragBeginCursor_(M_MAX_UNSIGNED),
cursorBlinkRate_(1.0f),
cursorBlinkTimer_(0.0f),
maxLength_(0),
@ -144,16 +144,16 @@ void LineEdit::OnClick(const IntVector2& position, const IntVector2& screenPosit
}
}
void LineEdit::OnDragStart(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
void LineEdit::OnDragBegin(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
{
dragStartCursor_ = GetCharIndex(position);
dragBeginCursor_ = GetCharIndex(position);
}
void LineEdit::OnDragMove(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
{
if (cursorMovable_ && textSelectable_)
{
unsigned start = dragStartCursor_;
unsigned start = dragBeginCursor_;
unsigned current = GetCharIndex(position);
if (start != M_MAX_UNSIGNED && current != M_MAX_UNSIGNED)
{
@ -235,7 +235,7 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
if (cursorMovable_ && cursorPosition_ > 0)
{
if (textSelectable_ && qualifiers & QUAL_SHIFT && !text_->GetSelectionLength())
dragStartCursor_ = cursorPosition_;
dragBeginCursor_ = cursorPosition_;
if (qualifiers & QUAL_CTRL)
cursorPosition_ = 0;
@ -245,7 +245,7 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
if (textSelectable_ && qualifiers & QUAL_SHIFT)
{
unsigned start = dragStartCursor_;
unsigned start = dragBeginCursor_;
unsigned current = cursorPosition_;
if (start < current)
text_->SetSelection(start, current - start);
@ -261,7 +261,7 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
if (cursorMovable_ && cursorPosition_ < line_.LengthUTF8())
{
if (textSelectable_ && qualifiers & QUAL_SHIFT && !text_->GetSelectionLength())
dragStartCursor_ = cursorPosition_;
dragBeginCursor_ = cursorPosition_;
if (qualifiers & QUAL_CTRL)
cursorPosition_ = line_.LengthUTF8();
@ -271,7 +271,7 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
if (textSelectable_ && qualifiers & QUAL_SHIFT)
{
unsigned start = dragStartCursor_;
unsigned start = dragBeginCursor_;
unsigned current = cursorPosition_;
if (start < current)
text_->SetSelection(start, current - start);

Просмотреть файл

@ -50,8 +50,8 @@ public:
/// React to mouse click.
virtual void OnClick(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag start.
virtual void OnDragStart(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag begin.
virtual void OnDragBegin(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag motion.
virtual void OnDragMove(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to drag and drop test. Return true to signal that the drop is acceptable.
@ -121,8 +121,8 @@ protected:
int lastFontSize_;
/// Text edit cursor position.
unsigned cursorPosition_;
/// Drag start edit cursor position.
unsigned dragStartCursor_;
/// Drag begin cursor position.
unsigned dragBeginCursor_;
/// Cursor blink rate.
float cursorBlinkRate_;
/// Cursor blink timer.

Просмотреть файл

@ -95,10 +95,10 @@ void Slider::OnHover(const IntVector2& position, const IntVector2& screenPositio
hovering_ = knob_->IsInside(screenPosition, true);
}
void Slider::OnDragStart(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
void Slider::OnDragBegin(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
{
dragStartCursor_ = position;
dragStartPosition_ = knob_->GetPosition();
dragBeginCursor_ = position;
dragBeginPosition_ = knob_->GetPosition();
dragSlider_ = knob_->IsInside(screenPosition, true);
}
@ -108,17 +108,17 @@ void Slider::OnDragMove(const IntVector2& position, const IntVector2& screenPosi
return;
float newValue = value_;
IntVector2 delta = position - dragStartCursor_;
IntVector2 delta = position - dragBeginCursor_;
if (orientation_ == O_HORIZONTAL)
{
int newX = Clamp(dragStartPosition_.x_ + delta.x_, 0, GetWidth() - knob_->GetWidth());
int newX = Clamp(dragBeginPosition_.x_ + delta.x_, 0, GetWidth() - knob_->GetWidth());
knob_->SetPosition(newX, 0);
newValue = (float)newX * range_ / (float)(GetWidth() - knob_->GetWidth());
}
else
{
int newY = Clamp(dragStartPosition_.y_ + delta.y_, 0, GetHeight() - knob_->GetHeight());
int newY = Clamp(dragBeginPosition_.y_ + delta.y_, 0, GetHeight() - knob_->GetHeight());
knob_->SetPosition(0, newY);
newValue = (float)newY * range_ / (float)(GetHeight() - knob_->GetHeight());
}

Просмотреть файл

@ -46,8 +46,8 @@ public:
virtual void Update(float timeStep);
/// React to mouse hover.
virtual void OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag start.
virtual void OnDragStart(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag begin.
virtual void OnDragBegin(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag motion.
virtual void OnDragMove(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag end.
@ -87,8 +87,8 @@ protected:
float value_;
/// Internal flag of whether the slider is being dragged.
bool dragSlider_;
/// Original mouse cursor position at drag start.
IntVector2 dragStartCursor_;
/// Original slider position at drag start.
IntVector2 dragStartPosition_;
/// Original mouse cursor position at drag begin.
IntVector2 dragBeginCursor_;
/// Original slider position at drag begin.
IntVector2 dragBeginPosition_;
};

Просмотреть файл

@ -31,6 +31,7 @@
#include "Font.h"
#include "Graphics.h"
#include "GraphicsEvents.h"
#include "Input.h"
#include "InputEvents.h"
#include "LineEdit.h"
#include "ListView.h"
@ -62,10 +63,13 @@ UI::UI(Context* context) :
initialized_(false)
{
SubscribeToEvent(E_SCREENMODE, HANDLER(UI, HandleScreenMode));
SubscribeToEvent(E_MOUSEMOVE, HANDLER(UI, HandleMouseMove));
SubscribeToEvent(E_MOUSEBUTTONDOWN, HANDLER(UI, HandleMouseButtonDown));
SubscribeToEvent(E_MOUSEBUTTONUP, HANDLER(UI, HandleMouseButtonUp));
SubscribeToEvent(E_MOUSEMOVE, HANDLER(UI, HandleMouseMove));
SubscribeToEvent(E_MOUSEWHEEL, HANDLER(UI, HandleMouseWheel));
SubscribeToEvent(E_TOUCHBEGIN, HANDLER(UI, HandleTouchBegin));
SubscribeToEvent(E_TOUCHEND, HANDLER(UI, HandleTouchEnd));
SubscribeToEvent(E_TOUCHMOVE, HANDLER(UI, HandleTouchMove));
SubscribeToEvent(E_KEYDOWN, HANDLER(UI, HandleKeyDown));
SubscribeToEvent(E_CHAR, HANDLER(UI, HandleChar));
SubscribeToEvent(E_POSTUPDATE, HANDLER(UI, HandlePostUpdate));
@ -206,6 +210,20 @@ void UI::Update(float timeStep)
cursor_->SetShape(dragElement_ == element ? CS_ACCEPTDROP : CS_REJECTDROP);
}
// Touch hover
Input* input = GetSubsystem<Input>();
if (input)
{
unsigned numTouches = input->GetNumTouches();
for (unsigned i = 0; i < numTouches; ++i)
{
TouchState touch = input->GetTouch(i);
WeakPtr<UIElement> element(GetElementAt(touch.position_));
if (element)
element->OnHover(element->ScreenToElement(touch.position_), touch.position_, MOUSEB_LEFT, 0, 0);
}
}
Update(timeStep, rootElement_);
}
@ -665,42 +683,6 @@ void UI::HandleScreenMode(StringHash eventType, VariantMap& eventData)
rootElement_->SetSize(eventData[P_WIDTH].GetInt(), eventData[P_HEIGHT].GetInt());
}
void UI::HandleMouseMove(StringHash eventType, VariantMap& eventData)
{
using namespace MouseMove;
mouseButtons_ = eventData[P_BUTTONS].GetInt();
qualifiers_ = eventData[P_QUALIFIERS].GetInt();
if (cursor_)
{
const IntVector2& rootSize = rootElement_->GetSize();
// Move cursor only when visible
if (cursor_->IsVisible())
{
IntVector2 pos = cursor_->GetPosition();
pos.x_ += eventData[P_DX].GetInt();
pos.y_ += eventData[P_DY].GetInt();
pos.x_ = Clamp(pos.x_, 0, rootSize.x_ - 1);
pos.y_ = Clamp(pos.y_, 0, rootSize.y_ - 1);
cursor_->SetPosition(pos);
}
if (dragElement_ && mouseButtons_)
{
IntVector2 pos = cursor_->GetPosition();
if (dragElement_->IsActive() && dragElement_->IsVisible())
dragElement_->OnDragMove(dragElement_->ScreenToElement(pos), pos, mouseButtons_, qualifiers_, cursor_);
else
{
dragElement_->OnDragEnd(dragElement_->ScreenToElement(pos), pos, cursor_);
dragElement_.Reset();
}
}
}
}
void UI::HandleMouseButtonDown(StringHash eventType, VariantMap& eventData)
{
mouseButtons_ = eventData[MouseButtonDown::P_BUTTONS].GetInt();
@ -728,7 +710,7 @@ void UI::HandleMouseButtonDown(StringHash eventType, VariantMap& eventData)
if (element && !dragElement_ && mouseButtons_ == MOUSEB_LEFT)
{
dragElement_ = element;
element->OnDragStart(element->ScreenToElement(pos), pos, mouseButtons_, qualifiers_, cursor_);
element->OnDragBegin(element->ScreenToElement(pos), pos, mouseButtons_, qualifiers_, cursor_);
}
}
else
@ -757,7 +739,7 @@ void UI::HandleMouseButtonUp(StringHash eventType, VariantMap& eventData)
mouseButtons_ = eventData[P_BUTTONS].GetInt();
qualifiers_ = eventData[P_QUALIFIERS].GetInt();
if (cursor_ && (cursor_->IsVisible())|| (dragElement_))
if (cursor_ && (cursor_->IsVisible()) || (dragElement_))
{
IntVector2 pos = cursor_->GetPosition();
@ -799,6 +781,42 @@ void UI::HandleMouseButtonUp(StringHash eventType, VariantMap& eventData)
}
}
void UI::HandleMouseMove(StringHash eventType, VariantMap& eventData)
{
using namespace MouseMove;
mouseButtons_ = eventData[P_BUTTONS].GetInt();
qualifiers_ = eventData[P_QUALIFIERS].GetInt();
if (cursor_)
{
const IntVector2& rootSize = rootElement_->GetSize();
// Move cursor only when visible
if (cursor_->IsVisible())
{
IntVector2 pos = cursor_->GetPosition();
pos.x_ += eventData[P_DX].GetInt();
pos.y_ += eventData[P_DY].GetInt();
pos.x_ = Clamp(pos.x_, 0, rootSize.x_ - 1);
pos.y_ = Clamp(pos.y_, 0, rootSize.y_ - 1);
cursor_->SetPosition(pos);
}
if (dragElement_ && mouseButtons_)
{
IntVector2 pos = cursor_->GetPosition();
if (dragElement_->IsActive() && dragElement_->IsVisible())
dragElement_->OnDragMove(dragElement_->ScreenToElement(pos), pos, mouseButtons_, qualifiers_, cursor_);
else
{
dragElement_->OnDragEnd(dragElement_->ScreenToElement(pos), pos, cursor_);
dragElement_.Reset();
}
}
}
}
void UI::HandleMouseWheel(StringHash eventType, VariantMap& eventData)
{
using namespace MouseWheel;
@ -825,6 +843,114 @@ void UI::HandleMouseWheel(StringHash eventType, VariantMap& eventData)
}
}
void UI::HandleTouchBegin(StringHash eventType, VariantMap& eventData)
{
using namespace TouchBegin;
IntVector2 pos(eventData[P_X].GetInt(), eventData[P_Y].GetInt());
WeakPtr<UIElement> element(GetElementAt(pos));
if (element)
{
// Handle focusing & bringing to front
SetFocusElement(element);
element->BringToFront();
// Handle click
element->OnClick(element->ScreenToElement(pos), pos, MOUSEB_LEFT, 0, 0);
// Handle start of drag. OnClick() may have caused destruction of the element, so check the pointer again
if (element && !dragElement_ )
{
dragElement_ = element;
element->OnDragBegin(element->ScreenToElement(pos), pos, MOUSEB_LEFT, 0, 0);
}
}
else
{
// If clicked over no element, or a disabled element, lose focus
SetFocusElement(0);
}
using namespace UIMouseClick;
VariantMap clickEventData;
clickEventData[UIMouseClick::P_ELEMENT] = (void*)element.Get();
clickEventData[UIMouseClick::P_X] = pos.x_;
clickEventData[UIMouseClick::P_Y] = pos.y_;
clickEventData[UIMouseClick::P_BUTTON] = MOUSEB_LEFT;
clickEventData[UIMouseClick::P_BUTTONS] = MOUSEB_LEFT;
clickEventData[UIMouseClick::P_QUALIFIERS] = 0;
SendEvent(E_UIMOUSECLICK, clickEventData);
}
void UI::HandleTouchEnd(StringHash eventType, VariantMap& eventData)
{
using namespace TouchEnd;
IntVector2 pos(eventData[P_X].GetInt(), eventData[P_Y].GetInt());
// Transmit hover end to the position where the finger was lifted
WeakPtr<UIElement> element(GetElementAt(pos));
if (element)
element->OnHover(element->ScreenToElement(pos), pos, 0, 0, 0);
if (dragElement_)
{
if (dragElement_->IsActive() && dragElement_->IsVisible())
{
dragElement_->OnDragEnd(dragElement_->ScreenToElement(pos), pos, cursor_);
// Drag and drop finish
bool dragSource = dragElement_ && (dragElement_->GetDragDropMode() & DD_SOURCE) != 0;
if (dragSource)
{
WeakPtr<UIElement> target(GetElementAt(pos));
bool dragTarget = target && (target->GetDragDropMode() & DD_TARGET) != 0;
bool dragDropFinish = dragSource && dragTarget && target != dragElement_;
if (dragDropFinish)
{
bool accept = target->OnDragDropFinish(dragElement_);
// OnDragDropFinish() may have caused destruction of the elements, so check the pointers again
if (accept && dragElement_ && target)
{
using namespace DragDropFinish;
VariantMap eventData;
eventData[P_SOURCE] = (void*)dragElement_.Get();
eventData[P_TARGET] = (void*)target.Get();
eventData[P_ACCEPT] = accept;
SendEvent(E_DRAGDROPFINISH, eventData);
}
}
}
}
dragElement_.Reset();
}
}
void UI::HandleTouchMove(StringHash eventType, VariantMap& eventData)
{
using namespace TouchMove;
IntVector2 pos(eventData[P_X].GetInt(), eventData[P_Y].GetInt());
if (dragElement_)
{
if (dragElement_->IsActive() && dragElement_->IsVisible())
dragElement_->OnDragMove(dragElement_->ScreenToElement(pos), pos, MOUSEB_LEFT, 0, 0);
else
{
dragElement_->OnDragEnd(dragElement_->ScreenToElement(pos), pos, 0);
dragElement_.Reset();
}
}
}
void UI::HandleKeyDown(StringHash eventType, VariantMap& eventData)
{
using namespace KeyDown;

Просмотреть файл

@ -97,14 +97,20 @@ private:
void LoadLayout(UIElement* current, const XMLElement& elem, XMLFile* styleFile);
/// Handle screen mode event.
void HandleScreenMode(StringHash eventType, VariantMap& eventData);
/// Handle mouse move event.
void HandleMouseMove(StringHash eventType, VariantMap& eventData);
/// Handle mouse button down event.
void HandleMouseButtonDown(StringHash eventType, VariantMap& eventData);
/// Handle mouse button up event.
void HandleMouseButtonUp(StringHash eventType, VariantMap& eventData);
/// Handle mouse move event.
void HandleMouseMove(StringHash eventType, VariantMap& eventData);
/// Handle mouse wheel event.
void HandleMouseWheel(StringHash eventType, VariantMap& eventData);
/// Handle touch begin event.
void HandleTouchBegin(StringHash eventType, VariantMap& eventData);
/// Handle touch end event.
void HandleTouchEnd(StringHash eventType, VariantMap& eventData);
/// Handle touch move event.
void HandleTouchMove(StringHash eventType, VariantMap& eventData);
/// Handle keypress event.
void HandleKeyDown(StringHash eventType, VariantMap& eventData);
/// Handle character event.

Просмотреть файл

@ -264,7 +264,7 @@ void UIElement::OnClick(const IntVector2& position, const IntVector2& screenPosi
{
}
void UIElement::OnDragStart(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
void UIElement::OnDragBegin(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
{
}

Просмотреть файл

@ -122,8 +122,8 @@ public:
virtual void OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse click.
virtual void OnClick(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag start.
virtual void OnDragStart(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag begin.
virtual void OnDragBegin(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag motion.
virtual void OnDragMove(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag end.

Просмотреть файл

@ -77,7 +77,7 @@ void Window::OnHover(const IntVector2& position, const IntVector2& screenPositio
SetCursorShape(dragMode_, cursor);
}
void Window::OnDragStart(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
void Window::OnDragBegin(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
{
if (buttons != MOUSEB_LEFT || !CheckAlignment())
{
@ -85,9 +85,9 @@ void Window::OnDragStart(const IntVector2& position, const IntVector2& screenPos
return;
}
dragStartCursor_ = screenPosition;
dragStartPosition_ = GetPosition();
dragStartSize_ = GetSize();
dragBeginCursor_ = screenPosition;
dragBeginPosition_ = GetPosition();
dragBeginSize_ = GetSize();
dragMode_ = GetDragMode(position);
SetCursorShape(dragMode_, cursor);
}
@ -97,49 +97,49 @@ void Window::OnDragMove(const IntVector2& position, const IntVector2& screenPosi
if (dragMode_ == DRAG_NONE)
return;
IntVector2 delta = screenPosition - dragStartCursor_;
IntVector2 delta = screenPosition - dragBeginCursor_;
switch (dragMode_)
{
case DRAG_MOVE:
SetPosition(dragStartPosition_ + delta);
SetPosition(dragBeginPosition_ + delta);
break;
case DRAG_RESIZE_TOPLEFT:
SetPosition(dragStartPosition_ + delta);
SetSize(dragStartSize_ - delta);
SetPosition(dragBeginPosition_ + delta);
SetSize(dragBeginSize_ - delta);
break;
case DRAG_RESIZE_TOP:
SetPosition(dragStartPosition_.x_, dragStartPosition_.y_ + delta.y_);
SetSize(dragStartSize_.x_, dragStartSize_.y_ - delta.y_);
SetPosition(dragBeginPosition_.x_, dragBeginPosition_.y_ + delta.y_);
SetSize(dragBeginSize_.x_, dragBeginSize_.y_ - delta.y_);
break;
case DRAG_RESIZE_TOPRIGHT:
SetPosition(dragStartPosition_.x_, dragStartPosition_.y_ + delta.y_);
SetSize(dragStartSize_.x_ + delta.x_, dragStartSize_.y_ - delta.y_);
SetPosition(dragBeginPosition_.x_, dragBeginPosition_.y_ + delta.y_);
SetSize(dragBeginSize_.x_ + delta.x_, dragBeginSize_.y_ - delta.y_);
break;
case DRAG_RESIZE_RIGHT:
SetSize(dragStartSize_.x_ + delta.x_, dragStartSize_.y_);
SetSize(dragBeginSize_.x_ + delta.x_, dragBeginSize_.y_);
break;
case DRAG_RESIZE_BOTTOMRIGHT:
SetSize(dragStartSize_ + delta);
SetSize(dragBeginSize_ + delta);
break;
case DRAG_RESIZE_BOTTOM:
SetSize(dragStartSize_.x_, dragStartSize_.y_ + delta.y_);
SetSize(dragBeginSize_.x_, dragBeginSize_.y_ + delta.y_);
break;
case DRAG_RESIZE_BOTTOMLEFT:
SetPosition(dragStartPosition_.x_ + delta.x_, dragStartPosition_.y_);
SetSize(dragStartSize_.x_ - delta.x_, dragStartSize_.y_ + delta.y_);
SetPosition(dragBeginPosition_.x_ + delta.x_, dragBeginPosition_.y_);
SetSize(dragBeginSize_.x_ - delta.x_, dragBeginSize_.y_ + delta.y_);
break;
case DRAG_RESIZE_LEFT:
SetPosition(dragStartPosition_.x_ + delta.x_, dragStartPosition_.y_);
SetSize(dragStartSize_.x_ - delta.x_, dragStartSize_.y_);
SetPosition(dragBeginPosition_.x_ + delta.x_, dragBeginPosition_.y_);
SetSize(dragBeginSize_.x_ - delta.x_, dragBeginSize_.y_);
break;
default:
@ -224,6 +224,9 @@ WindowDragMode Window::GetDragMode(const IntVector2& position) const
void Window::SetCursorShape(WindowDragMode mode, Cursor* cursor) const
{
if (!cursor)
return;
switch (mode)
{
case DRAG_RESIZE_TOP:

Просмотреть файл

@ -59,8 +59,8 @@ public:
virtual void SetStyle(const XMLElement& element);
/// React to mouse hover.
virtual void OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag start.
virtual void OnDragStart(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag begin.
virtual void OnDragBegin(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag motion.
virtual void OnDragMove(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
/// React to mouse drag end.
@ -98,10 +98,10 @@ protected:
IntRect resizeBorder_;
/// Current drag mode.
WindowDragMode dragMode_;
/// Mouse position at drag start.
IntVector2 dragStartCursor_;
/// Original position at drag start.
IntVector2 dragStartPosition_;
/// Original size at drag start.
IntVector2 dragStartSize_;
/// Mouse position at drag begin.
IntVector2 dragBeginCursor_;
/// Original position at drag begin.
IntVector2 dragBeginPosition_;
/// Original size at drag begin.
IntVector2 dragBeginSize_;
};

Просмотреть файл

@ -17,7 +17,7 @@ uniform sampler2DShadow sShadowMap;
uniform samplerCube sFaceSelectCubeMap;
uniform samplerCube sIndirectionCubeMap;
#else
uniform sampler2D sShadowMap;
uniform mediump sampler2D sShadowMap;
#endif
vec3 DecodeNormal(vec4 normalInput)

Просмотреть файл

@ -18,6 +18,9 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
// Modified by Lasse Öörni for Urho3D
#include "SDL_config.h"
#include "SDL_stdinc.h"
#include "SDL_assert.h"
@ -73,6 +76,9 @@ static jmethodID midAudioQuit;
static float fLastAccelerometer[3];
static bool bHasNewData;
// Application files dir
static char* mFilesDir = 0;
/*******************************************************************************
Functions called by JNI
*******************************************************************************/
@ -91,11 +97,30 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
return JNI_VERSION_1_4;
}
extern "C" const char* SDL_Android_GetFilesDir()
{
return mFilesDir;
}
// Called before SDL_main() to initialize JNI bindings
extern "C" void SDL_Android_Init(JNIEnv* env, jclass cls)
extern "C" void SDL_Android_Init(JNIEnv* env, jclass cls, jstring filesDir)
{
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init()");
// Copy the files dir
const char *str;
str = env->GetStringUTFChars(filesDir, 0);
if (str)
{
if (mFilesDir)
free(mFilesDir);
size_t length = strlen(str) + 1;
mFilesDir = (char*)malloc(length);
memcpy(mFilesDir, str, length);
env->ReleaseStringUTFChars(filesDir, str);
}
mEnv = env;
mActivityClass = (jclass)env->NewGlobalRef(cls);
@ -103,7 +128,7 @@ extern "C" void SDL_Android_Init(JNIEnv* env, jclass cls)
"createGLContext","(II)Z");
midFlipBuffers = mEnv->GetStaticMethodID(mActivityClass,
"flipBuffers","()V");
midAudioInit = mEnv->GetStaticMethodID(mActivityClass,
midAudioInit = mEnv->GetStaticMethodID(mActivityClass,
"audioInit", "(IZZI)Ljava/lang/Object;");
midAudioWriteShortBuffer = mEnv->GetStaticMethodID(mActivityClass,
"audioWriteShortBuffer", "([S)V");
@ -165,53 +190,53 @@ extern "C" void Java_org_libsdl_app_SDLActivity_onNativeAccel(
// Quit
extern "C" void Java_org_libsdl_app_SDLActivity_nativeQuit(
JNIEnv* env, jclass cls)
{
// Inject a SDL_QUIT event
SDL_Event event;
event.type=SDL_SYSEVENT_TERMINATE;
event.sysevent.data=NULL;
if (SDL_SysEventHandler)
SDL_SysEventHandler(&event);
else SDL_SendQuit();
}
// Pause
extern "C" void Java_org_libsdl_app_SDLActivity_nativePause(
JNIEnv* env, jclass cls)
{
SDL_Event event;
event.type=SDL_SYSEVENT_WILL_SUSPEND;
event.sysevent.data=NULL;
if (SDL_SysEventHandler)
SDL_SysEventHandler(&event);
event.type=SDL_SYSEVENT_SUSPEND;
event.sysevent.data=NULL;
if (SDL_SysEventHandler)
SDL_SysEventHandler(&event);
else if (Android_Window) {
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
}
JNIEnv* env, jclass cls)
{
// Inject a SDL_QUIT event
SDL_Event event;
event.type=SDL_SYSEVENT_TERMINATE;
event.sysevent.data=NULL;
if (SDL_SysEventHandler)
SDL_SysEventHandler(&event);
else SDL_SendQuit();
}
// Pause
extern "C" void Java_org_libsdl_app_SDLActivity_nativePause(
JNIEnv* env, jclass cls)
{
SDL_Event event;
event.type=SDL_SYSEVENT_WILL_SUSPEND;
event.sysevent.data=NULL;
if (SDL_SysEventHandler)
SDL_SysEventHandler(&event);
event.type=SDL_SYSEVENT_SUSPEND;
event.sysevent.data=NULL;
if (SDL_SysEventHandler)
SDL_SysEventHandler(&event);
else if (Android_Window) {
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
}
}
// Resume
extern "C" void Java_org_libsdl_app_SDLActivity_nativeResume(
JNIEnv* env, jclass cls)
{
SDL_Event event;
event.type=SDL_SYSEVENT_WILL_RESUME;
event.sysevent.data=NULL;
if (SDL_SysEventHandler)
SDL_SysEventHandler(&event);
event.type=SDL_SYSEVENT_RESUME;
event.sysevent.data=NULL;
if (SDL_SysEventHandler)
SDL_SysEventHandler(&event);
else if (Android_Window) {
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESTORED, 0, 0);
}
extern "C" void Java_org_libsdl_app_SDLActivity_nativeResume(
JNIEnv* env, jclass cls)
{
SDL_Event event;
event.type=SDL_SYSEVENT_WILL_RESUME;
event.sysevent.data=NULL;
if (SDL_SysEventHandler)
SDL_SysEventHandler(&event);
event.type=SDL_SYSEVENT_RESUME;
event.sysevent.data=NULL;
if (SDL_SysEventHandler)
SDL_SysEventHandler(&event);
else if (Android_Window) {
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESTORED, 0, 0);
}
}
extern "C" void Java_org_libsdl_app_SDLActivity_nativeRunAudioThread(

1349
ThirdParty/SDL/src/events/SDL_gesture.c поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -13,13 +13,13 @@
#include <jni.h>
// Called before SDL_main() to initialize JNI bindings in SDL library
extern "C" void SDL_Android_Init(JNIEnv* env, jclass cls);
extern "C" void SDL_Android_Init(JNIEnv* env, jclass cls, jstring filesDir);
// Start up the SDL app
extern "C" void Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject obj)
extern "C" void Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jstring filesDir)
{
/* This interface could expand with ABI negotiation, calbacks, etc. */
SDL_Android_Init(env, cls);
SDL_Android_Init(env, cls, filesDir);
/* Run the application code! */
int status;

Просмотреть файл

@ -96,7 +96,7 @@ void Run()
#ifdef ANDROID
// Can not pass script name on Android, so choose a hardcoded default
scriptFileName = "Scripts/TestScene.as";
scriptFileName = "Scripts/NinjaSnowWar.as";
#endif
// Show usage if not found