Moved to SDL 2.0 + IME support
This commit is contained in:
parent
463e1d2053
commit
87aedb702c
@ -9,9 +9,9 @@ set(OS_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
set(CMAKE_PREFIX_PATH Sources/Externals)
|
||||
|
||||
include(FindSDL)
|
||||
if(NOT SDL_FOUND)
|
||||
message(FATAL_ERROR "OpenSDL not found, set ENV{SDLDIR} to point to OpenSDL, and optionally set the cmake var SDL_LIBRARY_TEMP to the lib dir")
|
||||
include(cmake/FindSDL2.cmake)
|
||||
if(NOT SDL2_FOUND)
|
||||
message(FATAL_ERROR "SDL 2.0 not found, set ENV{SDL2DIR} to point to SDL 2.0, and optionally set the cmake var SDL2_LIBRARY_TEMP to the lib dir")
|
||||
endif()
|
||||
|
||||
include(FindOpenGL)
|
||||
@ -152,7 +152,7 @@ endif()
|
||||
configure_file("${PROJECT_SOURCE_DIR}/OpenSpades.h.in" "${PROJECT_BINARY_DIR}/OpenSpades.h")
|
||||
configure_file("${PROJECT_SOURCE_DIR}/OpenSpades.rc.in" "${PROJECT_BINARY_DIR}/OpenSpades.rc")
|
||||
include_directories("${PROJECT_BINARY_DIR}")
|
||||
include_directories("${SDL_INCLUDE_DIR}")
|
||||
include_directories("${SDL2_INCLUDE_DIR}")
|
||||
if(OPENGL_INCLUDE_DIR)
|
||||
include_directories("${OPENGL_INCLUDE_DIR}")
|
||||
endif()
|
||||
|
@ -164,8 +164,7 @@
|
||||
E8B6B74317EA0B2000E35523 /* IThirdPersonToolSkin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B74117EA0B1500E35523 /* IThirdPersonToolSkin.cpp */; };
|
||||
E8B6B74617EA0F2600E35523 /* IGrenadeSkin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B74417EA0F1B00E35523 /* IGrenadeSkin.cpp */; };
|
||||
E8B6B74917EA12EC00E35523 /* IWeaponSkin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B74717EA12E100E35523 /* IWeaponSkin.cpp */; };
|
||||
E8CF0396178EDA75000683D4 /* SDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8CF0395178EDA75000683D4 /* SDL.framework */; };
|
||||
E8CF0398178EDA86000683D4 /* SDL_net.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8CF0397178EDA86000683D4 /* SDL_net.framework */; };
|
||||
E8B93AD518559EC700BD01E1 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8B93AD418559EC600BD01E1 /* SDL2.framework */; };
|
||||
E8CF039A178EDABD000683D4 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8CF0399178EDABD000683D4 /* OpenAL.framework */; };
|
||||
E8CF039C178EDAC9000683D4 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E8CF039B178EDAC9000683D4 /* libz.dylib */; };
|
||||
E8CF03A8178EDF6A000683D4 /* IRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03A6178EDF6A000683D4 /* IRenderer.cpp */; };
|
||||
@ -239,7 +238,6 @@
|
||||
E8EE08A117B8F4B000631987 /* GLRadiosityRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8EE089F17B8F4B000631987 /* GLRadiosityRenderer.cpp */; };
|
||||
E8F74CE5183F86AE0085AA54 /* View.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CE3183F86AE0085AA54 /* View.cpp */; };
|
||||
E8F74CE9183F8B9D0085AA54 /* Runner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CE7183F8B9D0085AA54 /* Runner.cpp */; };
|
||||
E8F74CEB183F92DA0085AA54 /* SDLmain.m in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CEA183F92DA0085AA54 /* SDLmain.m */; };
|
||||
E8F74CEF183FBA9C0085AA54 /* MainScreenHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CED183FBA9C0085AA54 /* MainScreenHelper.cpp */; };
|
||||
E8F74CF2183FBB070085AA54 /* MainScreenHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CF0183FBB070085AA54 /* MainScreenHelper.cpp */; };
|
||||
E8F74CF51840D4CC0085AA54 /* Config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CF31840D4CC0085AA54 /* Config.cpp */; };
|
||||
@ -619,9 +617,8 @@
|
||||
E8B6B74517EA0F1E00E35523 /* IGrenadeSkin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGrenadeSkin.h; sourceTree = "<group>"; };
|
||||
E8B6B74717EA12E100E35523 /* IWeaponSkin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IWeaponSkin.cpp; sourceTree = "<group>"; };
|
||||
E8B6B74817EA12E500E35523 /* IWeaponSkin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IWeaponSkin.h; sourceTree = "<group>"; };
|
||||
E8B93AD418559EC600BD01E1 /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = ../../../../../Library/Frameworks/SDL2.framework; sourceTree = "<group>"; };
|
||||
E8CF0385178ED9D2000683D4 /* OpenSpades */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = OpenSpades; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E8CF0395178EDA75000683D4 /* SDL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL.framework; path = ../../../../../Library/Frameworks/SDL.framework; sourceTree = "<group>"; };
|
||||
E8CF0397178EDA86000683D4 /* SDL_net.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL_net.framework; path = ../../../../../Library/Frameworks/SDL_net.framework; sourceTree = "<group>"; };
|
||||
E8CF0399178EDABD000683D4 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; };
|
||||
E8CF039B178EDAC9000683D4 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
|
||||
E8CF03A6178EDF6A000683D4 /* IRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRenderer.cpp; path = Sources/Client/IRenderer.cpp; sourceTree = SOURCE_ROOT; };
|
||||
@ -791,8 +788,7 @@
|
||||
E8CF03C5178EE78C000683D4 /* OpenGL.framework in Frameworks */,
|
||||
E8CF039C178EDAC9000683D4 /* libz.dylib in Frameworks */,
|
||||
E8CF039A178EDABD000683D4 /* OpenAL.framework in Frameworks */,
|
||||
E8CF0398178EDA86000683D4 /* SDL_net.framework in Frameworks */,
|
||||
E8CF0396178EDA75000683D4 /* SDL.framework in Frameworks */,
|
||||
E8B93AD518559EC700BD01E1 /* SDL2.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1235,6 +1231,7 @@
|
||||
E8CF037C178ED9D2000683D4 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E8B93AD418559EC600BD01E1 /* SDL2.framework */,
|
||||
E844888617D26699005105D0 /* libcurl.dylib */,
|
||||
E8E446AB17A02EC700BE8855 /* Supporting Files */,
|
||||
E8E44691179CE7B800BE8855 /* libpng15.15.dylib */,
|
||||
@ -1249,8 +1246,6 @@
|
||||
E8CF03C4178EE78C000683D4 /* OpenGL.framework */,
|
||||
E8CF039B178EDAC9000683D4 /* libz.dylib */,
|
||||
E8CF0399178EDABD000683D4 /* OpenAL.framework */,
|
||||
E8CF0397178EDA86000683D4 /* SDL_net.framework */,
|
||||
E8CF0395178EDA75000683D4 /* SDL.framework */,
|
||||
E8CF041817905609000683D4 /* Resources */,
|
||||
E8CF0387178ED9D2000683D4 /* Sources */,
|
||||
E8CF0386178ED9D2000683D4 /* Products */,
|
||||
@ -1873,7 +1868,6 @@
|
||||
E844888417D2633C005105D0 /* json_writer.cpp in Sources */,
|
||||
E844888A17D39CD3005105D0 /* ErrorDialog.cpp in Sources */,
|
||||
E8D2ACE317D704E600BE5490 /* GLColorCorrectionFilter.cpp in Sources */,
|
||||
E8F74CEB183F92DA0085AA54 /* SDLmain.m in Sources */,
|
||||
E8B6B68F17DE27B500E35523 /* as_atomic.cpp in Sources */,
|
||||
E8B6B69017DE27B500E35523 /* as_builder.cpp in Sources */,
|
||||
E8B6B69117DE27B500E35523 /* as_bytecode.cpp in Sources */,
|
||||
@ -1979,8 +1973,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
/Library/Frameworks/SDL.framework/Headers,
|
||||
/Library/Frameworks/SDL_net.framework/Headers,
|
||||
/Library/Frameworks/SDL2.framework/Headers,
|
||||
/usr/local/include/FL/images,
|
||||
/usr/local/include,
|
||||
Sources/ENet/include,
|
||||
@ -2024,8 +2017,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
/Library/Frameworks/SDL.framework/Headers,
|
||||
/Library/Frameworks/SDL_net.framework/Headers,
|
||||
/Library/Frameworks/SDL2.framework/Headers,
|
||||
/usr/local/include/FL/images,
|
||||
/usr/local/include,
|
||||
Sources/ENet/include,
|
||||
@ -2043,6 +2035,10 @@
|
||||
E8CF038F178ED9D2000683D4 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(LOCAL_LIBRARY_DIR)/Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/opt/X11/lib,
|
||||
@ -2054,6 +2050,10 @@
|
||||
E8CF0390178ED9D2000683D4 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(LOCAL_LIBRARY_DIR)/Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/opt/X11/lib,
|
||||
|
@ -77,5 +77,73 @@
|
||||
renderer.DrawImage(image, AABB2(x + border, y + border, w - border - border, h - border - border),
|
||||
AABB2(border, border, iw - border - border, ih - border - border));
|
||||
}
|
||||
|
||||
/** Returns the byte index for a certain character index. */
|
||||
int GetByteIndexForString(string s, int charIndex, int start = 0) {
|
||||
int len = s.length;
|
||||
while(start < len && charIndex > 0) {
|
||||
int c = s[start];
|
||||
if((c & 0x80) == 0) {
|
||||
charIndex--;
|
||||
start += 1;
|
||||
}else if((c & 0xe0) == 0xc0) {
|
||||
charIndex--;
|
||||
start += 2;
|
||||
}else if((c & 0xf0) == 0xe0) {
|
||||
charIndex--;
|
||||
start += 3;
|
||||
}else if((c & 0xf8) == 0xf0) {
|
||||
charIndex--;
|
||||
start += 4;
|
||||
}else if((c & 0xfc) == 0xf8) {
|
||||
charIndex--;
|
||||
start += 5;
|
||||
}else if((c & 0xfe) == 0xfc) {
|
||||
charIndex--;
|
||||
start += 6;
|
||||
}else{
|
||||
// invalid!
|
||||
charIndex--;
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
if(start > len) start = len;
|
||||
return start;
|
||||
}
|
||||
|
||||
/** Returns the byte index for a certain character index. */
|
||||
int GetCharIndexForString(string s, int byteIndex, int start = 0) {
|
||||
int len = s.length;
|
||||
int charIndex = 0;
|
||||
while(start < len && start < byteIndex && byteIndex > 0) {
|
||||
int c = s[start];
|
||||
if((c & 0x80) == 0) {
|
||||
charIndex++;
|
||||
start += 1;
|
||||
}else if((c & 0xe0) == 0xc0) {
|
||||
charIndex++;
|
||||
start += 2;
|
||||
}else if((c & 0xf0) == 0xe0) {
|
||||
charIndex++;
|
||||
start += 3;
|
||||
}else if((c & 0xf8) == 0xf0) {
|
||||
charIndex++;
|
||||
start += 4;
|
||||
}else if((c & 0xfc) == 0xf8) {
|
||||
charIndex++;
|
||||
start += 5;
|
||||
}else if((c & 0xfe) == 0xfc) {
|
||||
charIndex++;
|
||||
start += 6;
|
||||
}else{
|
||||
// invalid!
|
||||
charIndex++;
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
return charIndex;
|
||||
}
|
||||
}
|
||||
|
@ -54,12 +54,28 @@ namespace spades {
|
||||
manager.MouseEvent(x, y);
|
||||
}
|
||||
|
||||
void WheelEvent(float x, float y) {
|
||||
manager.WheelEvent(x, y);
|
||||
}
|
||||
|
||||
void KeyEvent(string key, bool down) {
|
||||
manager.KeyEvent(key, down);
|
||||
}
|
||||
|
||||
void CharEvent(string text) {
|
||||
manager.CharEvent(text);
|
||||
void TextInputEvent(string text) {
|
||||
manager.TextInputEvent(text);
|
||||
}
|
||||
|
||||
void TextEditingEvent(string text, int start, int len) {
|
||||
manager.TextEditingEvent(text, start, len);
|
||||
}
|
||||
|
||||
bool AcceptsTextInput() {
|
||||
return manager.AcceptsTextInput;
|
||||
}
|
||||
|
||||
AABB2 GetTextInputRect() {
|
||||
return manager.TextInputRect;
|
||||
}
|
||||
|
||||
void RunFrame(float dt) {
|
||||
|
@ -73,12 +73,28 @@ namespace spades {
|
||||
manager.MouseEvent(x, y);
|
||||
}
|
||||
|
||||
void WheelEvent(float x, float y) {
|
||||
manager.WheelEvent(x, y);
|
||||
}
|
||||
|
||||
void KeyEvent(string key, bool down) {
|
||||
manager.KeyEvent(key, down);
|
||||
}
|
||||
|
||||
void CharEvent(string text) {
|
||||
manager.CharEvent(text);
|
||||
void TextInputEvent(string text) {
|
||||
manager.TextInputEvent(text);
|
||||
}
|
||||
|
||||
void TextEditingEvent(string text, int start, int len) {
|
||||
manager.TextEditingEvent(text, start, len);
|
||||
}
|
||||
|
||||
bool AcceptsTextInput() {
|
||||
return manager.AcceptsTextInput;
|
||||
}
|
||||
|
||||
AABB2 GetTextInputRect() {
|
||||
return manager.TextInputRect;
|
||||
}
|
||||
|
||||
private SceneDefinition SetupCamera(SceneDefinition sceneDef,
|
||||
|
@ -385,6 +385,20 @@ namespace spades {
|
||||
return true;
|
||||
}
|
||||
|
||||
AABB2 TextInputRect {
|
||||
get {
|
||||
Vector2 textPos = TextOrigin;
|
||||
Vector2 siz = this.Size;
|
||||
string text = Text;
|
||||
int cursorPos = CursorPosition;
|
||||
Font@ font = this.Font;
|
||||
float width = font.Measure(text.substr(0, cursorPos)).x;
|
||||
float fontHeight = font.Measure("A").y;
|
||||
return AABB2(textPos.x + width, textPos.y,
|
||||
siz.x - textPos.x - width, fontHeight);
|
||||
}
|
||||
}
|
||||
|
||||
private int PointToCharIndex(float x) {
|
||||
x -= TextOrigin.x;
|
||||
if(x < 0.f) return 0;
|
||||
@ -394,17 +408,22 @@ namespace spades {
|
||||
float lastWidth = 0.f;
|
||||
Font@ font = this.Font;
|
||||
// FIXME: use binary search for better performance?
|
||||
// FIXME: support multi-byte charset
|
||||
int idx = 0;
|
||||
for(int i = 1; i <= len; i++) {
|
||||
float width = font.Measure(text.substr(0, i)).x;
|
||||
int lastIdx = idx;
|
||||
idx = GetByteIndexForString(text, 1, idx);
|
||||
float width = font.Measure(text.substr(0, idx)).x;
|
||||
if(width > x) {
|
||||
if(x < (lastWidth + width) * 0.5f) {
|
||||
return i - 1;
|
||||
return lastIdx;
|
||||
} else {
|
||||
return i;
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
lastWidth = width;
|
||||
if(idx >= len) {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
@ -429,7 +448,10 @@ namespace spades {
|
||||
if(SelectionLength > 0) {
|
||||
SelectedText = "";
|
||||
} else {
|
||||
Select(SelectionStart - 1, 1);
|
||||
int pos = CursorPosition;
|
||||
int cIdx = GetCharIndexForString(Text, CursorPosition);
|
||||
int bIdx = GetByteIndexForString(Text, cIdx - 1);
|
||||
Select(bIdx, pos - bIdx);
|
||||
SelectedText = "";
|
||||
}
|
||||
OnChanged();
|
||||
@ -457,8 +479,8 @@ namespace spades {
|
||||
CursorPosition = ClampCursorPosition(CursorPosition - 1);
|
||||
}else {
|
||||
if(SelectionLength == 0) {
|
||||
// FIXME: support multi-byte charset
|
||||
Select(CursorPosition - 1);
|
||||
int cIdx = GetCharIndexForString(Text, CursorPosition);
|
||||
Select(GetByteIndexForString(Text, cIdx - 1));
|
||||
} else {
|
||||
Select(SelectionStart);
|
||||
}
|
||||
@ -469,8 +491,8 @@ namespace spades {
|
||||
CursorPosition = ClampCursorPosition(CursorPosition + 1);
|
||||
}else {
|
||||
if(SelectionLength == 0) {
|
||||
// FIXME: support multi-byte charset
|
||||
Select(CursorPosition + 1);
|
||||
int cIdx = GetCharIndexForString(Text, CursorPosition);
|
||||
Select(GetByteIndexForString(Text, cIdx + 1));
|
||||
} else {
|
||||
Select(SelectionEnd);
|
||||
}
|
||||
@ -555,6 +577,14 @@ namespace spades {
|
||||
renderer.DrawImage(img, AABB2(x - 1.f, y, 2, h));
|
||||
}
|
||||
|
||||
void DrawEditingLine(float x, float y, float w, float h) {
|
||||
Renderer@ renderer = Manager.Renderer;
|
||||
renderer.ColorNP = Vector4(1.f, 1.f, 1.f, .3f);
|
||||
|
||||
Image@ img = renderer.RegisterImage("Gfx/White.tga");
|
||||
renderer.DrawImage(img, AABB2(x, y + h, w, 2.f));
|
||||
}
|
||||
|
||||
void Render() {
|
||||
Renderer@ renderer = Manager.Renderer;
|
||||
Vector2 pos = ScreenPosition;
|
||||
@ -563,6 +593,20 @@ namespace spades {
|
||||
Vector2 textPos = TextOrigin + pos;
|
||||
string text = Text;
|
||||
|
||||
string composition = this.EditingText;
|
||||
int editStart = this.TextEditingRangeStart;
|
||||
int editLen = this.TextEditingRangeLength;
|
||||
|
||||
int markStart = SelectionStart;
|
||||
int markEnd = SelectionEnd;
|
||||
|
||||
if(composition.length > 0){
|
||||
this.SelectedText = "";
|
||||
markStart = SelectionStart + editStart;
|
||||
markEnd = markStart + editLen;
|
||||
text = text.substr(0, SelectionStart) + composition + text.substr(SelectionStart);
|
||||
}
|
||||
|
||||
if(text.length == 0){
|
||||
if(IsEnabled) {
|
||||
font.Draw(Placeholder, textPos, TextScale, PlaceholderColor);
|
||||
@ -575,8 +619,8 @@ namespace spades {
|
||||
float fontHeight = font.Measure("A").y;
|
||||
|
||||
// draw selection
|
||||
int start = SelectionStart;
|
||||
int end = SelectionEnd;
|
||||
int start = markStart;
|
||||
int end = markEnd;
|
||||
if(end == start) {
|
||||
float x = font.Measure(text.substr(0, start)).x;
|
||||
DrawBeam(x + textPos.x, textPos.y, fontHeight);
|
||||
@ -585,7 +629,18 @@ namespace spades {
|
||||
float x2 = font.Measure(text.substr(0, end)).x;
|
||||
DrawHighlight(textPos.x + x1, textPos.y, x2 - x1, fontHeight);
|
||||
}
|
||||
|
||||
// draw composition underline
|
||||
if(composition.length > 0) {
|
||||
start = SelectionStart;
|
||||
end = start + composition.length;
|
||||
float x1 = font.Measure(text.substr(0, start)).x;
|
||||
float x2 = font.Measure(text.substr(0, end)).x;
|
||||
DrawEditingLine(textPos.x + x1, textPos.y, x2 - x1, fontHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,11 @@ namespace spades {
|
||||
bool IsControlPressed = false;
|
||||
bool IsShiftPressed = false;
|
||||
|
||||
// IME (Input Method Editor) support
|
||||
string EditingText;
|
||||
int EditingStart = 0;
|
||||
int EditingLength = 0;
|
||||
|
||||
private UIElement@ mouseCapturedElement;
|
||||
private UIElement@ mouseHoverElement;
|
||||
|
||||
@ -98,6 +103,13 @@ namespace spades {
|
||||
return e.Cursor;
|
||||
}
|
||||
|
||||
void WheelEvent(float x, float y) {
|
||||
UIElement@ e = GetMouseActiveElement();
|
||||
if(e !is null) {
|
||||
e.MouseWheel(y);
|
||||
}
|
||||
}
|
||||
|
||||
void MouseEvent(float x, float y) {
|
||||
MouseCursorPosition = Vector2(
|
||||
Clamp(MouseCursorPosition.x + x, 0.f, renderer.ScreenWidth),
|
||||
@ -128,6 +140,9 @@ namespace spades {
|
||||
void KeyPanic() {
|
||||
keyRepeater.KeyUp();
|
||||
charRepeater.KeyUp();
|
||||
EditingText = "";
|
||||
EditingStart = 0;
|
||||
EditingLength = 0;
|
||||
}
|
||||
|
||||
void KeyEvent(string key, bool down) {
|
||||
@ -193,14 +208,55 @@ namespace spades {
|
||||
}
|
||||
}
|
||||
|
||||
void CharEvent(string chr) {
|
||||
void TextInputEvent(string chr) {
|
||||
charRepeater.KeyDown(chr);
|
||||
HandleCharInner(chr);
|
||||
}
|
||||
|
||||
void TextEditingEvent(string chr, int start, int len) {
|
||||
EditingText = chr;
|
||||
EditingStart = GetByteIndexForString(chr, start);
|
||||
EditingLength = GetByteIndexForString(chr, len, EditingStart) - EditingStart;
|
||||
}
|
||||
|
||||
bool AcceptsTextInput {
|
||||
get {
|
||||
if(ActiveElement is null) {
|
||||
EditingText = "";
|
||||
EditingStart = 0;
|
||||
EditingLength = 0;
|
||||
}
|
||||
return ActiveElement !is null;
|
||||
}
|
||||
}
|
||||
|
||||
AABB2 TextInputRect {
|
||||
get {
|
||||
UIElement@ e = ActiveElement;
|
||||
if(e !is null) {
|
||||
AABB2 rt = e.TextInputRect;
|
||||
Vector2 off = e.ScreenPosition;
|
||||
rt.min += off;
|
||||
rt.max += off;
|
||||
return rt;
|
||||
}else{
|
||||
return AABB2();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleKeyInner(string key) {
|
||||
{
|
||||
UIElement@ e = ActiveElement;
|
||||
if(EditingText.length > 0) {
|
||||
// now text is being composed by IME.
|
||||
// ignore some keys to resolve confliction.
|
||||
if(key == "Escape" || key == "BackSpace" || key == "Left" || key == "Right" ||
|
||||
key == "Space" || key == "Enter" || key == "Up" || key == "Down" ||
|
||||
key == "Tab") {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(e !is null) {
|
||||
e.KeyDown(key);
|
||||
} else {
|
||||
@ -615,6 +671,44 @@ namespace spades {
|
||||
}
|
||||
}
|
||||
|
||||
// IME supports
|
||||
|
||||
AABB2 TextInputRect {
|
||||
get {
|
||||
return AABB2(0.f, 0.f, Size.x, Size.y);
|
||||
}
|
||||
}
|
||||
|
||||
int TextEditingRangeStart {
|
||||
get final {
|
||||
if(this.IsFocused) {
|
||||
return Manager.EditingStart;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int TextEditingRangeLength {
|
||||
get final {
|
||||
if(this.IsFocused) {
|
||||
return Manager.EditingLength;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string EditingText {
|
||||
get final {
|
||||
if(this.IsFocused) {
|
||||
return Manager.EditingText;
|
||||
}else{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnResized() {
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ add_dependencies(OpenSpades Angelscript Angelscript_addons)
|
||||
|
||||
if(WIN32)
|
||||
source_group("Resources" ${RESOURCE_FILES})
|
||||
foreach(LIB ${SDL_LIBRARY})
|
||||
foreach(LIB ${SDL2_LIBRARY})
|
||||
string(REGEX REPLACE "\\.lib$" ".dll" SDL_DLL ${LIB})
|
||||
if(EXISTS "${SDL_DLL}")
|
||||
add_custom_command(TARGET OpenSpades POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SDL_DLL}" "${CMAKE_BINARY_DIR}/bin/\$\(Configuration\)/")
|
||||
@ -87,7 +87,7 @@ source_group("ScriptBindings" FILES ${SCRIPTBINDING_FILES})
|
||||
source_group("libs\\unzip" FILES ${UNZIP_FILES})
|
||||
|
||||
|
||||
target_link_libraries(OpenSpades ${SDL_LIBRARY} ${OPENGL_LIBRARIES} ${GLEW_LIBRARY} ${FLTK_OS_LIBS} ${ZLIB_LIBRARIES} ${CURL_LIBRARY} ${CMAKE_DL_LIBS} ${ANGELSCRIPT_LIBS})
|
||||
target_link_libraries(OpenSpades ${SDL2_LIBRARY} ${OPENGL_LIBRARIES} ${GLEW_LIBRARY} ${FLTK_OS_LIBS} ${ZLIB_LIBRARIES} ${CURL_LIBRARY} ${CMAKE_DL_LIBS} ${ANGELSCRIPT_LIBS})
|
||||
|
||||
#todo: MACOSX_BUNDLE_ICON_FILE ?
|
||||
|
||||
|
@ -918,20 +918,63 @@ namespace spades {
|
||||
}
|
||||
}
|
||||
|
||||
void Client::CharEvent(const std::string &ch){
|
||||
void Client::WheelEvent(float x, float y) {
|
||||
SPADES_MARK_FUNCTION();
|
||||
|
||||
if(scriptedUI->NeedsInput()) {
|
||||
scriptedUI->CharEvent(ch);
|
||||
scriptedUI->WheelEvent(x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
if(y > .5f) {
|
||||
KeyEvent("WheelDown", true);
|
||||
KeyEvent("WheelDown", false);
|
||||
}else if(y < -.5f){
|
||||
KeyEvent("WheelUp", true);
|
||||
KeyEvent("WheelUp", false);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::TextInputEvent(const std::string &ch){
|
||||
SPADES_MARK_FUNCTION();
|
||||
|
||||
if(scriptedUI->NeedsInput()) {
|
||||
scriptedUI->TextInputEvent(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
if(ch == "/") {
|
||||
scriptedUI->EnterCommandWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void Client::TextEditingEvent(const std::string &ch,
|
||||
int start, int len) {
|
||||
SPADES_MARK_FUNCTION();
|
||||
|
||||
if(scriptedUI->NeedsInput()) {
|
||||
scriptedUI->TextEditingEvent(ch, start, len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool Client::AcceptsTextInput() {
|
||||
SPADES_MARK_FUNCTION();
|
||||
|
||||
if(scriptedUI->NeedsInput()) {
|
||||
return scriptedUI->AcceptsTextInput();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
AABB2 Client::GetTextInputRect() {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(scriptedUI->NeedsInput()) {
|
||||
return scriptedUI->GetTextInputRect();
|
||||
}
|
||||
return AABB2();
|
||||
}
|
||||
|
||||
// TODO: this might not be a fast way
|
||||
//lm: ideally we should normalize the key when reading the config.
|
||||
static bool CheckKey(const std::string& cfg,
|
||||
|
@ -235,9 +235,14 @@ namespace spades {
|
||||
|
||||
virtual void Closing();
|
||||
virtual void MouseEvent(float x, float y);
|
||||
virtual void WheelEvent(float x, float y);
|
||||
virtual void KeyEvent(const std::string&,
|
||||
bool down);
|
||||
virtual void CharEvent(const std::string&);
|
||||
bool down);
|
||||
virtual void TextInputEvent(const std::string&);
|
||||
virtual void TextEditingEvent(const std::string&,
|
||||
int start, int len);
|
||||
virtual bool AcceptsTextInput();
|
||||
virtual AABB2 GetTextInputRect();
|
||||
|
||||
void SetWorld(World *);
|
||||
World *GetWorld() const { return world; }
|
||||
|
@ -87,6 +87,20 @@ namespace spades {
|
||||
c.ExecuteChecked();
|
||||
}
|
||||
|
||||
void ClientUI::WheelEvent(float x, float y) {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(!ui){
|
||||
return;
|
||||
}
|
||||
|
||||
static ScriptFunction func("ClientUI", "void WheelEvent(float, float)");
|
||||
ScriptContextHandle c = func.Prepare();
|
||||
c->SetObject(&*ui);
|
||||
c->SetArgFloat(0, x);
|
||||
c->SetArgFloat(1, y);
|
||||
c.ExecuteChecked();
|
||||
}
|
||||
|
||||
void ClientUI::KeyEvent(const std::string & key, bool down) {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(!ui){
|
||||
@ -101,12 +115,12 @@ namespace spades {
|
||||
c.ExecuteChecked();
|
||||
}
|
||||
|
||||
void ClientUI::CharEvent(const std::string &ch) {
|
||||
void ClientUI::TextInputEvent(const std::string &ch) {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(!ui){
|
||||
return;
|
||||
}
|
||||
static ScriptFunction func("ClientUI", "void CharEvent(string)");
|
||||
static ScriptFunction func("ClientUI", "void TextInputEvent(string)");
|
||||
ScriptContextHandle c = func.Prepare();
|
||||
std::string k = ch;
|
||||
c->SetObject(&*ui);
|
||||
@ -114,6 +128,46 @@ namespace spades {
|
||||
c.ExecuteChecked();
|
||||
}
|
||||
|
||||
void ClientUI::TextEditingEvent(const std::string &ch,
|
||||
int start, int len) {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(!ui){
|
||||
return;
|
||||
}
|
||||
static ScriptFunction func("ClientUI", "void TextEditingEvent(string,int,int)");
|
||||
ScriptContextHandle c = func.Prepare();
|
||||
std::string k = ch;
|
||||
c->SetObject(&*ui);
|
||||
c->SetArgObject(0, reinterpret_cast<void*>(&k));
|
||||
c->SetArgDWord(1, static_cast<asDWORD>(start));
|
||||
c->SetArgDWord(2, static_cast<asDWORD>(len));
|
||||
c.ExecuteChecked();
|
||||
}
|
||||
|
||||
bool ClientUI::AcceptsTextInput() {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(!ui){
|
||||
return false;
|
||||
}
|
||||
static ScriptFunction func("ClientUI", "bool AcceptsTextInput()");
|
||||
ScriptContextHandle c = func.Prepare();
|
||||
c->SetObject(&*ui);
|
||||
c.ExecuteChecked();
|
||||
return c->GetReturnByte() != 0;
|
||||
}
|
||||
|
||||
AABB2 ClientUI::GetTextInputRect() {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(!ui){
|
||||
return AABB2();
|
||||
}
|
||||
static ScriptFunction func("ClientUI", "AABB2 GetTextInputRect()");
|
||||
ScriptContextHandle c = func.Prepare();
|
||||
c->SetObject(&*ui);
|
||||
c.ExecuteChecked();
|
||||
return *reinterpret_cast<AABB2*>(c->GetReturnObject());
|
||||
}
|
||||
|
||||
bool ClientUI::WantsClientToBeClosed() {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(!ui){
|
||||
|
@ -56,9 +56,14 @@ namespace spades {
|
||||
client::IAudioDevice *GetAudioDevice() { return &*audioDevice; }
|
||||
|
||||
void MouseEvent(float x, float y);
|
||||
void WheelEvent(float x, float y);
|
||||
void KeyEvent(const std::string&,
|
||||
bool down);
|
||||
void CharEvent(const std::string&);
|
||||
bool down);
|
||||
void TextInputEvent(const std::string&);
|
||||
void TextEditingEvent(const std::string&,
|
||||
int start, int len);
|
||||
bool AcceptsTextInput();
|
||||
AABB2 GetTextInputRect();
|
||||
|
||||
void RunFrame(float dt);
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "Debug.h"
|
||||
#include "ThreadLocalStorage.h"
|
||||
#include "ConcurrentDispatch.h"
|
||||
#include <typeinfo>
|
||||
|
||||
namespace spades {
|
||||
|
||||
@ -90,8 +91,13 @@ namespace spades {
|
||||
if(threadInfo)
|
||||
return;
|
||||
|
||||
const std::type_info& info = typeid(*this);
|
||||
const char *name = info.name();
|
||||
if(name == nullptr)
|
||||
name = "(null)";
|
||||
|
||||
threadId = 0;
|
||||
threadInfo = SDL_CreateThread(InternalRunner, this);
|
||||
threadInfo = SDL_CreateThread(InternalRunner, name, this);
|
||||
}
|
||||
|
||||
void Thread::Join() {
|
||||
|
@ -90,6 +90,25 @@ namespace spades {
|
||||
c.ExecuteChecked();
|
||||
}
|
||||
|
||||
|
||||
void MainScreen::WheelEvent(float x, float y) {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(subview){
|
||||
subview->WheelEvent(x, y);
|
||||
return;
|
||||
}
|
||||
if(!ui){
|
||||
return;
|
||||
}
|
||||
|
||||
static ScriptFunction func("MainScreenUI", "void WheelEvent(float, float)");
|
||||
ScriptContextHandle c = func.Prepare();
|
||||
c->SetObject(&*ui);
|
||||
c->SetArgFloat(0, x);
|
||||
c->SetArgFloat(1, y);
|
||||
c.ExecuteChecked();
|
||||
}
|
||||
|
||||
void MainScreen::KeyEvent(const std::string & key, bool down) {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(subview){
|
||||
@ -108,16 +127,16 @@ namespace spades {
|
||||
c.ExecuteChecked();
|
||||
}
|
||||
|
||||
void MainScreen::CharEvent(const std::string &ch) {
|
||||
void MainScreen::TextInputEvent(const std::string &ch) {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(subview){
|
||||
subview->CharEvent(ch);
|
||||
subview->TextInputEvent(ch);
|
||||
return;
|
||||
}
|
||||
if(!ui){
|
||||
return;
|
||||
}
|
||||
static ScriptFunction func("MainScreenUI", "void CharEvent(string)");
|
||||
static ScriptFunction func("MainScreenUI", "void TextInputEvent(string)");
|
||||
ScriptContextHandle c = func.Prepare();
|
||||
std::string k = ch;
|
||||
c->SetObject(&*ui);
|
||||
@ -125,6 +144,56 @@ namespace spades {
|
||||
c.ExecuteChecked();
|
||||
}
|
||||
|
||||
void MainScreen::TextEditingEvent(const std::string &ch,
|
||||
int start, int len) {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(subview){
|
||||
subview->TextEditingEvent(ch, start, len);
|
||||
return;
|
||||
}
|
||||
if(!ui){
|
||||
return;
|
||||
}
|
||||
static ScriptFunction func("MainScreenUI", "void TextEditingEvent(string, int, int)");
|
||||
ScriptContextHandle c = func.Prepare();
|
||||
std::string k = ch;
|
||||
c->SetObject(&*ui);
|
||||
c->SetArgObject(0, reinterpret_cast<void*>(&k));
|
||||
c->SetArgDWord(1, static_cast<asDWORD>(start));
|
||||
c->SetArgDWord(2, static_cast<asDWORD>(len));
|
||||
c.ExecuteChecked();
|
||||
}
|
||||
|
||||
bool MainScreen::AcceptsTextInput() {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(subview){
|
||||
return subview->AcceptsTextInput();
|
||||
}
|
||||
if(!ui){
|
||||
return false;
|
||||
}
|
||||
static ScriptFunction func("MainScreenUI", "bool AcceptsTextInput()");
|
||||
ScriptContextHandle c = func.Prepare();
|
||||
c->SetObject(&*ui);
|
||||
c.ExecuteChecked();
|
||||
return c->GetReturnByte() != 0;
|
||||
}
|
||||
|
||||
AABB2 MainScreen::GetTextInputRect() {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(subview){
|
||||
return subview->GetTextInputRect();
|
||||
}
|
||||
if(!ui){
|
||||
return AABB2();
|
||||
}
|
||||
static ScriptFunction func("MainScreenUI", "AABB2 GetTextInputRect()");
|
||||
ScriptContextHandle c = func.Prepare();
|
||||
c->SetObject(&*ui);
|
||||
c.ExecuteChecked();
|
||||
return *reinterpret_cast<AABB2*>(c->GetReturnObject());
|
||||
}
|
||||
|
||||
bool MainScreen::WantsToBeClosed() {
|
||||
SPADES_MARK_FUNCTION();
|
||||
if(!ui){
|
||||
|
@ -60,7 +60,12 @@ namespace spades {
|
||||
virtual void MouseEvent(float x, float y);
|
||||
virtual void KeyEvent(const std::string&,
|
||||
bool down);
|
||||
virtual void CharEvent(const std::string&);
|
||||
virtual void TextInputEvent(const std::string&);
|
||||
virtual void TextEditingEvent(const std::string&,
|
||||
int start, int len);
|
||||
virtual bool AcceptsTextInput();
|
||||
virtual AABB2 GetTextInputRect();
|
||||
virtual void WheelEvent(float x, float y);
|
||||
|
||||
virtual void RunFrame(float dt);
|
||||
|
||||
|
@ -383,23 +383,41 @@ void MainWindow::CheckGLCapability() {
|
||||
SPLog("Initializing SDL for capability query");
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
SDL_Rect **modes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN |
|
||||
SDL_DOUBLEBUF);
|
||||
if(modes && modes != (SDL_Rect **)-1){
|
||||
g_modes.clear();
|
||||
for(size_t i = 0; modes[i]; i++){
|
||||
SDL_Rect mode = *(modes[i]);
|
||||
int idDisplay = 0;
|
||||
|
||||
int numDisplayMode = SDL_GetNumDisplayModes(idDisplay);
|
||||
SDL_DisplayMode mode;
|
||||
g_modes.clear();
|
||||
if(numDisplayMode > 0){
|
||||
for(int i = 0; i < numDisplayMode; i++) {
|
||||
SDL_GetDisplayMode(idDisplay, i, &mode);
|
||||
if(mode.w < 800 || mode.h < 600)
|
||||
continue;
|
||||
g_modes.push_back(spades::IntVector3::Make(mode.w, mode.h, 0));
|
||||
SPLog("Video Mode Found: %dx%d", mode.w, mode.h);
|
||||
}
|
||||
|
||||
}else{
|
||||
SPLog("Failed to get video mode list. Presetting default list");
|
||||
g_modes.push_back(spades::IntVector3::Make(800, 600, 0));
|
||||
g_modes.push_back(spades::IntVector3::Make(1024, 768, 0));
|
||||
g_modes.push_back(spades::IntVector3::Make(1280, 720, 0));
|
||||
g_modes.push_back(spades::IntVector3::Make(1920, 1080, 0));
|
||||
}
|
||||
|
||||
|
||||
bool capable = true;
|
||||
std::string msg;
|
||||
if(!SDL_SetVideoMode(1,1, 32, SDL_OPENGL|SDL_NOFRAME)){
|
||||
SDL_Window *window = SDL_CreateWindow("Querying OpenGL Capabilities",
|
||||
1, 1, 1, 1,
|
||||
SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS);
|
||||
if(window == nullptr) {
|
||||
SPLog("Failed to create SDL window: %s", SDL_GetError());
|
||||
}
|
||||
SDL_GLContext context = window ? SDL_GL_CreateContext(window) : nullptr;
|
||||
if(window != nullptr && context == nullptr) {
|
||||
SPLog("Failed to create OpenGL context: %s", SDL_GetError());
|
||||
}
|
||||
if(!context){
|
||||
// OpenGL initialization failed!
|
||||
outputGLRenderer->value("N/A");
|
||||
outputGLVersion->value("N/A");
|
||||
@ -417,6 +435,8 @@ void MainWindow::CheckGLCapability() {
|
||||
particleHighCapable = false;
|
||||
}else{
|
||||
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
|
||||
shaderHighCapable = true;
|
||||
postFilterHighCapable = true;
|
||||
particleHighCapable = true;
|
||||
@ -685,14 +705,16 @@ void MainWindow::CheckGLCapability() {
|
||||
" You cannot play OpenSpades.</b><br> <br>" + msg;
|
||||
}
|
||||
|
||||
SDL_GL_DeleteContext(context);
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
SPLog("SDL Capability Query Window finalized");
|
||||
|
||||
}
|
||||
msg = "<font face=Helvetica>" + msg + "</font><a name=last></a>";
|
||||
|
||||
glInfoView->value(msg.c_str());
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
SPLog("SDL video subsystem finalized");
|
||||
|
||||
|
||||
SPLog("System is OpenSpades capable: %s",
|
||||
capable ? "YES": "NO");
|
||||
|
@ -197,6 +197,9 @@ namespace spades {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: support text inputing for cg_smp runner.
|
||||
// see SDLRunner.cpp and grep SDL_StartTextInput
|
||||
|
||||
//Fl::check();
|
||||
}
|
||||
|
||||
|
@ -123,8 +123,19 @@ ReportError(err, __LINE__, __PRETTY_FUNCTION__); \
|
||||
func);
|
||||
}
|
||||
|
||||
SDLGLDevice::SDLGLDevice(SDL_Surface *s):
|
||||
surface(s) {
|
||||
SDLGLDevice::SDLGLDevice(SDL_Window *s):
|
||||
window(s) {
|
||||
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
context = SDL_GL_CreateContext(s);
|
||||
if(!context) {
|
||||
const char *err = SDL_GetError();
|
||||
SPLog("Failed to create GL context!: %s", err);
|
||||
SPRaise("Failed to create GL context: %s", err);
|
||||
}
|
||||
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
|
||||
#ifndef __APPLE__
|
||||
GLenum err = glewInit();
|
||||
if (GLEW_OK != err){
|
||||
@ -150,6 +161,10 @@ ReportError(err, __LINE__, __PRETTY_FUNCTION__); \
|
||||
while(glGetError() != GL_NO_ERROR);
|
||||
}
|
||||
|
||||
SDLGLDevice::~SDLGLDevice() {
|
||||
SDL_GL_DeleteContext(context);
|
||||
}
|
||||
|
||||
void SDLGLDevice::DepthRange(Float near, Float far){
|
||||
CheckExistence(glDepthRange);
|
||||
glDepthRange(near, far);
|
||||
@ -188,7 +203,7 @@ ReportError(err, __LINE__, __PRETTY_FUNCTION__); \
|
||||
void SDLGLDevice::Swap() {
|
||||
//glFinish();
|
||||
CheckErrorAlways();
|
||||
SDL_GL_SwapBuffers();
|
||||
SDL_GL_SwapWindow(window);
|
||||
#if 0
|
||||
Uint32 t = SDL_GetTicks();
|
||||
if(lastFrame == 0) t = lastFrame - 30;
|
||||
@ -2216,11 +2231,11 @@ ReportError(err, __LINE__, __PRETTY_FUNCTION__); \
|
||||
|
||||
|
||||
IGLDevice::Integer SDLGLDevice::ScreenWidth() {
|
||||
return surface->w;
|
||||
return w;
|
||||
}
|
||||
|
||||
IGLDevice::Integer SDLGLDevice::ScreenHeight() {
|
||||
return surface->h;
|
||||
return h;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -27,9 +27,12 @@
|
||||
namespace spades {
|
||||
namespace gui {
|
||||
class SDLGLDevice: public draw::IGLDevice {
|
||||
SDL_Surface *surface;
|
||||
SDL_Window *window;
|
||||
SDL_GLContext context;
|
||||
int w, h;
|
||||
public:
|
||||
SDLGLDevice(SDL_Surface *);
|
||||
SDLGLDevice(SDL_Window *);
|
||||
virtual ~SDLGLDevice();
|
||||
|
||||
virtual void DepthRange(Float near, Float far);
|
||||
virtual void Viewport(Integer x, Integer y,
|
||||
|
@ -54,13 +54,13 @@ namespace spades {
|
||||
case SDL_BUTTON_LEFT: return "LeftMouseButton";
|
||||
case SDL_BUTTON_RIGHT: return "RightMouseButton";
|
||||
case SDL_BUTTON_MIDDLE: return "MiddleMouseButton";
|
||||
case SDL_BUTTON_WHEELUP: return "WheelUp";
|
||||
case SDL_BUTTON_WHEELDOWN: return "WheelDown";
|
||||
case SDL_BUTTON_X1: return "MouseButton4";
|
||||
case SDL_BUTTON_X2: return "MouseButton5";
|
||||
default: return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
std::string SDLRunner::TranslateKey(const SDL_keysym &k){
|
||||
std::string SDLRunner::TranslateKey(const SDL_Keysym &k){
|
||||
SPADES_MARK_FUNCTION();
|
||||
|
||||
|
||||
@ -118,19 +118,10 @@ namespace spades {
|
||||
view->MouseEvent(event.motion.xrel, event.motion.yrel);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
view->WheelEvent(-event.wheel.x, -event.wheel.y);
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
if(event.key.keysym.unicode){
|
||||
int uni = event.key.keysym.unicode;
|
||||
if(uni > 0 && uni < 128 &&
|
||||
uni != 8 && // no backspace
|
||||
uni != 27 && // no escape
|
||||
uni != 13 && uni != 10 &&
|
||||
uni != 127){ // no enter
|
||||
std::string s;
|
||||
s += (char)uni;
|
||||
view->CharEvent(s);
|
||||
}
|
||||
}
|
||||
view->KeyEvent(TranslateKey(event.key.keysym),
|
||||
true);
|
||||
break;
|
||||
@ -138,6 +129,13 @@ namespace spades {
|
||||
view->KeyEvent(TranslateKey(event.key.keysym),
|
||||
false);
|
||||
break;
|
||||
case SDL_TEXTINPUT:
|
||||
view->TextInputEvent(event.text.text);
|
||||
break;
|
||||
case SDL_TEXTEDITING:
|
||||
view->TextEditingEvent(event.edit.text, event.edit.start, event.edit.length);
|
||||
break;
|
||||
/* TODO: activation/deactivation
|
||||
case SDL_ACTIVEEVENT:
|
||||
if( event.active.state & (SDL_APPACTIVE|SDL_APPINPUTFOCUS) ) { //any of the 2 is good
|
||||
if(event.active.gain){
|
||||
@ -150,7 +148,7 @@ namespace spades {
|
||||
SDL_ShowCursor(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -166,6 +164,7 @@ namespace spades {
|
||||
|
||||
bool lastShift = false;
|
||||
bool lastCtrl = false;
|
||||
bool editing = false;
|
||||
|
||||
SPLog("Starting Client Loop");
|
||||
|
||||
@ -212,6 +211,23 @@ namespace spades {
|
||||
}
|
||||
}
|
||||
|
||||
bool ed = view->AcceptsTextInput();
|
||||
if(ed && !editing) {
|
||||
SDL_StartTextInput();
|
||||
}else if(!ed && editing){
|
||||
SDL_StopTextInput();
|
||||
}
|
||||
editing = ed;
|
||||
if(editing){
|
||||
AABB2 rt = view->GetTextInputRect();
|
||||
SDL_Rect srt;
|
||||
srt.x = (int)rt.GetMinX();
|
||||
srt.y = (int)rt.GetMinY();
|
||||
srt.w = (int)rt.GetWidth();
|
||||
srt.h = (int)rt.GetHeight();
|
||||
SDL_SetTextInputRect(&srt);
|
||||
}
|
||||
|
||||
while(SDL_PollEvent(&event)) {
|
||||
ProcessEvent(event, view);
|
||||
}
|
||||
@ -226,44 +242,45 @@ namespace spades {
|
||||
SPADES_MARK_FUNCTION();
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
try{
|
||||
std::string caption;
|
||||
{
|
||||
std::string pkg = PACKAGE_STRING;
|
||||
caption = PACKAGE_STRING;
|
||||
#if !NDEBUG
|
||||
pkg.append( " DEBUG build" );
|
||||
caption.append( " DEBUG build" );
|
||||
#endif
|
||||
#ifdef OPENSPADES_COMPILER_STR
|
||||
pkg.append( " " OPENSPADES_COMPILER_STR ); //add compiler to window title
|
||||
caption.append( " " OPENSPADES_COMPILER_STR ); //add compiler to window title
|
||||
#endif
|
||||
SDL_WM_SetCaption(pkg.c_str(), pkg.c_str());
|
||||
}
|
||||
|
||||
SDL_Surface *surface;
|
||||
SDL_Window *window;
|
||||
|
||||
int sdlFlags = SDL_OPENGL | SDL_DOUBLEBUF;
|
||||
Uint32 sdlFlags;
|
||||
|
||||
sdlFlags = SDL_WINDOW_OPENGL;
|
||||
if(r_fullscreen)
|
||||
sdlFlags |= SDL_FULLSCREEN;
|
||||
sdlFlags |= SDL_WINDOW_FULLSCREEN;
|
||||
|
||||
// OpenGL core profile: supported by SDL 1.3 or later
|
||||
//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, r_depthBits);
|
||||
|
||||
surface = SDL_SetVideoMode(r_videoWidth, r_videoHeight, r_colorBits, sdlFlags);
|
||||
if(!surface){
|
||||
window = SDL_CreateWindow(caption.c_str(),
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
r_videoWidth, r_videoHeight, sdlFlags);
|
||||
|
||||
if(!window){
|
||||
std::string msg = SDL_GetError();
|
||||
SPRaise("Failed to initialize video device: %s", msg.c_str());
|
||||
SPRaise("Failed to create graphics window: %s", msg.c_str());
|
||||
}
|
||||
|
||||
|
||||
SDL_WM_GrabInput(SDL_GRAB_ON);
|
||||
SDL_EnableUNICODE(1);
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
SDL_ShowCursor(0);
|
||||
mActive = true;
|
||||
|
||||
{
|
||||
SDLGLDevice glDevice(surface);
|
||||
SDLGLDevice glDevice(window);
|
||||
Handle<draw::GLRenderer> renderer(new draw::GLRenderer(&glDevice), false);
|
||||
audio::ALDevice audio;
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace spades {
|
||||
class SDLRunner: public IRunnable {
|
||||
bool mActive;
|
||||
protected:
|
||||
std::string TranslateKey(const SDL_keysym&);
|
||||
std::string TranslateKey(const SDL_Keysym&);
|
||||
std::string TranslateButton(Uint8 b);
|
||||
virtual int GetModState();
|
||||
void ProcessEvent(SDL_Event& event,
|
||||
|
@ -21,6 +21,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/RefCountedObject.h>
|
||||
#include <Core/Math.h>
|
||||
|
||||
namespace spades {
|
||||
namespace gui {
|
||||
@ -33,7 +34,12 @@ namespace spades {
|
||||
virtual void MouseEvent(float x, float y) {}
|
||||
virtual void KeyEvent(const std::string&,
|
||||
bool down) {}
|
||||
virtual void CharEvent(const std::string&) {}
|
||||
virtual void TextInputEvent(const std::string&) {}
|
||||
virtual void TextEditingEvent(const std::string&,
|
||||
int start, int len) {}
|
||||
virtual bool AcceptsTextInput() { return false; }
|
||||
virtual AABB2 GetTextInputRect() { return AABB2(); }
|
||||
virtual void WheelEvent(float x, float y) {}
|
||||
|
||||
virtual void RunFrame(float dt) {}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user