commit
a2e741d540
@ -27,6 +27,8 @@
|
||||
500B20451C4B43BC0002B53F /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Bold.ttf"; sourceTree = "<group>"; };
|
||||
500B20461C4B43BC0002B53F /* Roboto-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Light.ttf"; sourceTree = "<group>"; };
|
||||
500B20471C4B43BC0002B53F /* Roboto-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Regular.ttf"; sourceTree = "<group>"; };
|
||||
504DFDEA1C4EA2CD00D3714A /* zahnrad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = zahnrad.h; path = ../../../zahnrad.h; sourceTree = "<group>"; };
|
||||
504DFDED1C4EA34800D3714A /* demo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = demo.c; path = ../../demo.c; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -60,9 +62,11 @@
|
||||
500B201E1C4B41870002B53F /* Mac_GL */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
504DFDED1C4EA34800D3714A /* demo.c */,
|
||||
500B203E1C4B43930002B53F /* ZahnradBackend.h */,
|
||||
500B203F1C4B43930002B53F /* ZahnradBackend.m */,
|
||||
500B20231C4B41870002B53F /* main.m */,
|
||||
504DFDEA1C4EA2CD00D3714A /* zahnrad.h */,
|
||||
500B20411C4B43A30002B53F /* zahnrad.c */,
|
||||
500B202A1C4B41880002B53F /* Info.plist */,
|
||||
);
|
||||
|
@ -3,7 +3,7 @@ Zahnrad for Mac OS X, iOS and tvOS
|
||||
|
||||
This is a bunch of experimental render backends for [Zahnrad](https://github.com/vurtun/zahnrad) a gorgeous immediate mode GUI toolkit.
|
||||
|
||||
Include are native versions for Mac OS X, iOS and tvOS. The Mac version is using OpenGL 3.2. iOS and tvOS are running on OpenGL ES 3.2.
|
||||
Included are native versions for Mac OS X, iOS and tvOS. The Mac version is using OpenGL 3.2. iOS and tvOS are running on OpenGL ES 3.2.
|
||||
|
||||
Versions utilising Metal are in the making.
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
#define SIMULATE_TOUCH 0
|
||||
|
||||
#if (TARGET_OS_IPHONE && (!TARGET_OS_TV)) || SIMULATE_TOUCH
|
||||
#define ZR_REFRESH_ON_EVENT_ONLY 1
|
||||
#define ZR_REFRESH_ON_EVENT_ONLY 0
|
||||
#define ZR_TOUCH_SCREEN 1
|
||||
#endif
|
||||
|
||||
@ -45,6 +45,7 @@
|
||||
|
||||
@interface ZahnradBackend : NSObject
|
||||
|
||||
|
||||
@property (readonly) GLVIEW* view;
|
||||
|
||||
- (instancetype) initWithView: (GLVIEW*) view;
|
||||
@ -56,3 +57,21 @@
|
||||
@end
|
||||
|
||||
|
||||
struct zr_context;
|
||||
struct zr_buffer;
|
||||
struct zr_allocator;
|
||||
struct zr_user_font;
|
||||
|
||||
|
||||
@interface ZahnradBackend (Adapter)
|
||||
|
||||
|
||||
- (struct zr_context*) createContextWithBuffer: (struct zr_buffer*) cmds
|
||||
allocator: (struct zr_allocator*) alloc
|
||||
defaultFont: (struct zr_user_font*) defFont;
|
||||
|
||||
- (int) fillFrame;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
@ -19,6 +19,18 @@
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#define MAX_VERTEX_MEMORY (512 * 1024)
|
||||
#define MAX_ELEMENT_MEMORY (128 * 1024)
|
||||
|
||||
|
||||
// This is the adapter for demo.c.
|
||||
// #else does provide a generic version to start
|
||||
// your own project.
|
||||
|
||||
#if 1
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -26,17 +38,106 @@
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "../../zahnrad.h"
|
||||
#include "zahnrad.h"
|
||||
#include "../demo.c"
|
||||
|
||||
#undef MAX
|
||||
#undef MIN
|
||||
|
||||
|
||||
#import "ZahnradBackend.h"
|
||||
|
||||
#define MAX_VERTEX_MEMORY (512 * 1024)
|
||||
#define MAX_ELEMENT_MEMORY (128 * 1024)
|
||||
|
||||
@implementation ZahnradBackend (Adapter)
|
||||
|
||||
static struct demo gui;
|
||||
|
||||
|
||||
- (struct zr_context*) createContextWithBuffer: (struct zr_buffer*) cmds
|
||||
allocator: (struct zr_allocator*) alloc
|
||||
defaultFont: (struct zr_user_font*) defFont
|
||||
{
|
||||
memset(&gui, 0, sizeof(gui));
|
||||
|
||||
zr_buffer_init(cmds, alloc, 4096);
|
||||
zr_init(&gui.ctx, alloc, defFont);
|
||||
|
||||
return &gui.ctx;
|
||||
}
|
||||
|
||||
|
||||
- (int) fillFrame;
|
||||
{
|
||||
return run_demo(&gui);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
#import "ZahnradBackend.h"
|
||||
#import "zahnrad.h"
|
||||
|
||||
|
||||
@implementation ZahnradBackend (Adapter)
|
||||
|
||||
static struct zr_context context;
|
||||
|
||||
|
||||
- (struct zr_context*) createContextWithBuffer: (struct zr_buffer*) cmds
|
||||
allocator: (struct zr_allocator*) alloc
|
||||
defaultFont: (struct zr_user_font*) defFont
|
||||
{
|
||||
memset(&context, 0, sizeof(context));
|
||||
|
||||
zr_buffer_init(cmds, alloc, 4096);
|
||||
zr_init(&context, alloc, defFont);
|
||||
|
||||
return &context;
|
||||
}
|
||||
|
||||
|
||||
- (int) fillFrame;
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@implementation ZahnradBackend
|
||||
{
|
||||
struct zr_context* context;
|
||||
|
||||
struct zr_allocator alloc;
|
||||
struct zr_user_font sysFnt;
|
||||
struct zr_font font;
|
||||
struct zr_draw_null_texture nullTexture;
|
||||
|
||||
struct zr_buffer cmds;
|
||||
NSMutableArray* bufferedCommands;
|
||||
NSMutableArray* events;
|
||||
|
||||
struct
|
||||
{
|
||||
GLuint vbo, vao, ebo;
|
||||
GLuint program;
|
||||
GLuint vertexShader;
|
||||
GLuint fragmentShader;
|
||||
GLint attributePosition;
|
||||
GLint attributeUV;
|
||||
GLint attributeColor;
|
||||
GLint uniformTexture;
|
||||
GLint uniformProjection;
|
||||
GLuint fontTexture;
|
||||
} device;
|
||||
}
|
||||
|
||||
|
||||
static void* mem_alloc(zr_handle unused, size_t size)
|
||||
@ -51,36 +152,6 @@ static void mem_free(zr_handle unused, void* ptr)
|
||||
}
|
||||
|
||||
|
||||
struct device
|
||||
{
|
||||
GLuint vbo, vao, ebo;
|
||||
GLuint prog;
|
||||
GLuint vert_shdr;
|
||||
GLuint frag_shdr;
|
||||
GLint attrib_pos;
|
||||
GLint attrib_uv;
|
||||
GLint attrib_col;
|
||||
GLint uniform_tex;
|
||||
GLint uniform_proj;
|
||||
GLuint font_tex;
|
||||
struct zr_draw_null_texture null;
|
||||
struct zr_buffer cmds;
|
||||
};
|
||||
|
||||
|
||||
@implementation ZahnradBackend
|
||||
{
|
||||
struct demo gui;
|
||||
struct device device;
|
||||
struct zr_font font;
|
||||
struct zr_user_font usrfnt;
|
||||
struct zr_allocator alloc;
|
||||
|
||||
NSMutableArray* events;
|
||||
NSMutableArray* drawCommands;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Setup -
|
||||
|
||||
|
||||
@ -91,7 +162,7 @@ struct device
|
||||
_view = view;
|
||||
|
||||
events = [NSMutableArray new];
|
||||
drawCommands = [NSMutableArray new];
|
||||
bufferedCommands = [NSMutableArray new];
|
||||
|
||||
[self setupGL];
|
||||
|
||||
@ -102,10 +173,9 @@ struct device
|
||||
alloc.alloc = mem_alloc;
|
||||
alloc.free = mem_free;
|
||||
|
||||
zr_buffer_init(&device.cmds, &alloc, 4096);
|
||||
usrfnt = [self fontFromUrl: fontURL height: 14 range: zr_font_default_glyph_ranges()];
|
||||
zr_init(&gui.ctx, &alloc, &usrfnt);
|
||||
sysFnt = [self fontFromUrl: fontURL height: 14 range: zr_font_default_glyph_ranges()];
|
||||
|
||||
context = [self createContextWithBuffer: &cmds allocator: &alloc defaultFont: &sysFnt];
|
||||
[self fillFrame];
|
||||
|
||||
return self;
|
||||
@ -149,67 +219,67 @@ struct device
|
||||
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
|
||||
"}\n";
|
||||
|
||||
device.prog = glCreateProgram();
|
||||
device.vert_shdr = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(device.vert_shdr, 1, &vss, 0);
|
||||
glCompileShader(device.vert_shdr);
|
||||
device.program = glCreateProgram();
|
||||
device.vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(device.vertexShader, 1, &vss, 0);
|
||||
glCompileShader(device.vertexShader);
|
||||
|
||||
#if defined(DEBUG)
|
||||
GLint logLength;
|
||||
glGetShaderiv(device.vert_shdr, GL_INFO_LOG_LENGTH, &logLength);
|
||||
glGetShaderiv(device.vertexShader, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0)
|
||||
{
|
||||
GLchar* log = (GLchar*)malloc(logLength);
|
||||
glGetShaderInfoLog(device.vert_shdr, logLength, &logLength, log);
|
||||
glGetShaderInfoLog(device.vertexShader, logLength, &logLength, log);
|
||||
NSLog(@"Shader compile log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
#endif
|
||||
|
||||
glGetShaderiv(device.vert_shdr, GL_COMPILE_STATUS, &status);
|
||||
glGetShaderiv(device.vertexShader, GL_COMPILE_STATUS, &status);
|
||||
assert(status == GL_TRUE);
|
||||
|
||||
device.frag_shdr = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(device.frag_shdr, 1, &fss, 0);
|
||||
glCompileShader(device.frag_shdr);
|
||||
device.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(device.fragmentShader, 1, &fss, 0);
|
||||
glCompileShader(device.fragmentShader);
|
||||
|
||||
#if defined(DEBUG)
|
||||
glGetShaderiv(device.frag_shdr, GL_INFO_LOG_LENGTH, &logLength);
|
||||
glGetShaderiv(device.fragmentShader, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0)
|
||||
{
|
||||
GLchar* log = (GLchar*)malloc(logLength);
|
||||
glGetShaderInfoLog(device.frag_shdr, logLength, &logLength, log);
|
||||
glGetShaderInfoLog(device.fragmentShader, logLength, &logLength, log);
|
||||
NSLog(@"Shader compile log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
#endif
|
||||
|
||||
glGetShaderiv(device.frag_shdr, GL_COMPILE_STATUS, &status);
|
||||
glGetShaderiv(device.fragmentShader, GL_COMPILE_STATUS, &status);
|
||||
assert(status == GL_TRUE);
|
||||
|
||||
glAttachShader(device.prog, device.vert_shdr);
|
||||
glAttachShader(device.prog, device.frag_shdr);
|
||||
glLinkProgram(device.prog);
|
||||
glAttachShader(device.program, device.vertexShader);
|
||||
glAttachShader(device.program, device.fragmentShader);
|
||||
glLinkProgram(device.program);
|
||||
|
||||
#if defined(DEBUG)
|
||||
glGetProgramiv(device.prog, GL_INFO_LOG_LENGTH, &logLength);
|
||||
glGetProgramiv(device.program, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0)
|
||||
{
|
||||
GLchar* log = (GLchar*)malloc(logLength);
|
||||
glGetProgramInfoLog(device.prog, logLength, &logLength, log);
|
||||
glGetProgramInfoLog(device.program, logLength, &logLength, log);
|
||||
NSLog(@"Program link log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
#endif
|
||||
|
||||
glGetProgramiv(device.prog, GL_LINK_STATUS, &status);
|
||||
glGetProgramiv(device.program, GL_LINK_STATUS, &status);
|
||||
assert(status == GL_TRUE);
|
||||
|
||||
device.uniform_tex = glGetUniformLocation(device.prog, "Texture");
|
||||
device.uniform_proj = glGetUniformLocation(device.prog, "ProjMtx");
|
||||
device.attrib_pos = glGetAttribLocation(device.prog, "Position");
|
||||
device.attrib_uv = glGetAttribLocation(device.prog, "TexCoord");
|
||||
device.attrib_col = glGetAttribLocation(device.prog, "Color");
|
||||
device.uniformTexture = glGetUniformLocation(device.program, "Texture");
|
||||
device.uniformProjection = glGetUniformLocation(device.program, "ProjMtx");
|
||||
device.attributePosition = glGetAttribLocation(device.program, "Position");
|
||||
device.attributeUV = glGetAttribLocation(device.program, "TexCoord");
|
||||
device.attributeColor = glGetAttribLocation(device.program, "Color");
|
||||
|
||||
// buffer setup
|
||||
GLsizei vs = sizeof(struct zr_draw_vertex);
|
||||
@ -229,13 +299,13 @@ struct device
|
||||
glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_MEMORY, NULL, GL_STREAM_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_MEMORY, NULL, GL_STREAM_DRAW);
|
||||
|
||||
glEnableVertexAttribArray((GLuint)device.attrib_pos);
|
||||
glEnableVertexAttribArray((GLuint)device.attrib_uv);
|
||||
glEnableVertexAttribArray((GLuint)device.attrib_col);
|
||||
glEnableVertexAttribArray((GLuint)device.attributePosition);
|
||||
glEnableVertexAttribArray((GLuint)device.attributeUV);
|
||||
glEnableVertexAttribArray((GLuint)device.attributeColor);
|
||||
|
||||
glVertexAttribPointer((GLuint)device.attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp);
|
||||
glVertexAttribPointer((GLuint)device.attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt);
|
||||
glVertexAttribPointer((GLuint)device.attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc);
|
||||
glVertexAttribPointer((GLuint)device.attributePosition, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp);
|
||||
glVertexAttribPointer((GLuint)device.attributeUV, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt);
|
||||
glVertexAttribPointer((GLuint)device.attributeColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
@ -297,8 +367,8 @@ struct device
|
||||
img = img_rgba;
|
||||
|
||||
// upload baked font image
|
||||
glGenTextures(1, &device.font_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, device.font_tex);
|
||||
glGenTextures(1, &device.fontTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, device.fontTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)img_width, (GLsizei)img_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img);
|
||||
@ -307,16 +377,15 @@ struct device
|
||||
free(img);
|
||||
|
||||
// default white pixel in a texture which is needed to draw primitives
|
||||
device.null.texture.id = (int)device.font_tex;
|
||||
device.null.uv = zr_vec2((custom.x + 0.5f) / (float)img_width,
|
||||
(custom.y + 0.5f) / (float)img_height);
|
||||
nullTexture.texture.id = (int)device.fontTexture;
|
||||
nullTexture.uv = zr_vec2((custom.x + 0.5f) / (float)img_width, (custom.y + 0.5f) / (float)img_height);
|
||||
|
||||
/* setup font with glyphes. IMPORTANT: the font only references the glyphes
|
||||
this was done to have the possibility to have multible fonts with one
|
||||
total glyph array. Not quite sure if it is a good thing since the
|
||||
glyphes have to be freed as well.
|
||||
*/
|
||||
zr_font_init(&font, (float)fontHeight, '?', glyphes, &baked_font, device.null.texture);
|
||||
zr_font_init(&font, (float)fontHeight, '?', glyphes, &baked_font, nullTexture.texture);
|
||||
|
||||
return zr_font_ref(&font);
|
||||
}
|
||||
@ -354,9 +423,9 @@ struct device
|
||||
};
|
||||
ortho[0][0] /= width;
|
||||
ortho[1][1] /= height;
|
||||
glUseProgram(device.prog);
|
||||
glUniform1i(device.uniform_tex, 0);
|
||||
glUniformMatrix4fv(device.uniform_proj, 1, GL_FALSE, &ortho[0][0]);
|
||||
glUseProgram(device.program);
|
||||
glUniform1i(device.uniformTexture, 0);
|
||||
glUniformMatrix4fv(device.uniformProjection, 1, GL_FALSE, &ortho[0][0]);
|
||||
|
||||
// activate vertex and element buffer
|
||||
glBindVertexArray(device.vao);
|
||||
@ -364,18 +433,18 @@ struct device
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, device.ebo);
|
||||
|
||||
// if draw commands have been buffered we will draw only those
|
||||
if (drawCommands.count)
|
||||
if (bufferedCommands.count)
|
||||
{
|
||||
const struct zr_draw_command* cmd;
|
||||
const zr_draw_index* offset = NULL;
|
||||
|
||||
// iterate over and execute each draw command
|
||||
for (NSData* data in drawCommands)
|
||||
for (NSData* data in bufferedCommands)
|
||||
{
|
||||
cmd = data.bytes;
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
|
||||
glScissor((GLint)(cmd->clip_rect.x * scale),
|
||||
(GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale),
|
||||
(GLint)((height - (cmd->clip_rect.y + cmd->clip_rect.h)) * scale),
|
||||
(GLint)(cmd->clip_rect.w * scale),
|
||||
(GLint)(cmd->clip_rect.h * scale));
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
|
||||
@ -384,8 +453,8 @@ struct device
|
||||
}
|
||||
else
|
||||
{
|
||||
// load draw vertexes & elements into vertex + element buffer
|
||||
void* vertexes = glMapBufferRange(GL_ARRAY_BUFFER, 0, MAX_VERTEX_MEMORY, GL_MAP_WRITE_BIT);
|
||||
// load draw vertices & elements into vertex + element buffer
|
||||
void* vertices = glMapBufferRange(GL_ARRAY_BUFFER, 0, MAX_VERTEX_MEMORY, GL_MAP_WRITE_BIT);
|
||||
void* elements = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, MAX_ELEMENT_MEMORY, GL_MAP_WRITE_BIT);
|
||||
|
||||
// fill converting configuration
|
||||
@ -395,13 +464,13 @@ struct device
|
||||
config.line_AA = ZR_ANTI_ALIASING_ON;
|
||||
config.circle_segment_count = 22;
|
||||
config.line_thickness = 1.0f;
|
||||
config.null = device.null;
|
||||
config.null = nullTexture;
|
||||
|
||||
// setup buffers to load vertexes and elements
|
||||
// setup buffers to load vertices and elements
|
||||
struct zr_buffer vbuf, ebuf;
|
||||
zr_buffer_init_fixed(&vbuf, vertexes, MAX_VERTEX_MEMORY);
|
||||
zr_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY);
|
||||
zr_buffer_init_fixed(&ebuf, elements, MAX_ELEMENT_MEMORY);
|
||||
zr_convert(&gui.ctx, &device.cmds, &vbuf, &ebuf, &config);
|
||||
zr_convert(context, &cmds, &vbuf, &ebuf, &config);
|
||||
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
|
||||
@ -410,15 +479,15 @@ struct device
|
||||
const struct zr_draw_command* cmd;
|
||||
const zr_draw_index* offset = NULL;
|
||||
|
||||
[drawCommands removeAllObjects];
|
||||
[bufferedCommands removeAllObjects];
|
||||
|
||||
// iterate over and execute each draw command
|
||||
zr_draw_foreach(cmd, &gui.ctx, &device.cmds)
|
||||
zr_draw_foreach(cmd, context, &cmds)
|
||||
{
|
||||
if (cmd->elem_count > 0)
|
||||
{
|
||||
#if ZR_REFRESH_ON_EVENT_ONLY
|
||||
[drawCommands addObject: [NSData dataWithBytes: cmd length: sizeof(struct zr_draw_command)]];
|
||||
[bufferedCommands addObject: [NSData dataWithBytes: cmd length: sizeof(struct zr_draw_command)]];
|
||||
#endif
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
|
||||
glScissor((GLint)(cmd->clip_rect.x * scale),
|
||||
@ -430,8 +499,8 @@ struct device
|
||||
}
|
||||
}
|
||||
|
||||
zr_clear(&gui.ctx);
|
||||
}
|
||||
zr_clear(context);
|
||||
}
|
||||
|
||||
// restore old state
|
||||
glUseProgram((GLuint)last_prog);
|
||||
@ -443,12 +512,6 @@ struct device
|
||||
}
|
||||
|
||||
|
||||
- (void) fillFrame
|
||||
{
|
||||
run_demo(&gui);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Events -
|
||||
|
||||
|
||||
@ -470,7 +533,7 @@ struct device
|
||||
NSArray* currentEvents = events.copy;
|
||||
[events removeAllObjects];
|
||||
|
||||
zr_input_begin(&gui.ctx);
|
||||
zr_input_begin(context);
|
||||
|
||||
for (NSDictionary* event in currentEvents)
|
||||
{
|
||||
@ -487,55 +550,55 @@ struct device
|
||||
|
||||
switch (type)
|
||||
{
|
||||
|
||||
#if ZR_REFRESH_ON_EVENT_ONLY || ZR_TOUCH_SCREEN
|
||||
|
||||
case 2: case 3: case 4:
|
||||
zr_input_motion(&gui.ctx, x, y);
|
||||
zr_input_motion(context, x, y);
|
||||
break;
|
||||
case 5:
|
||||
zr_input_motion(&gui.ctx, x, y);
|
||||
zr_input_end(&gui.ctx);
|
||||
zr_input_begin(&gui.ctx);
|
||||
zr_input_button(&gui.ctx, ZR_BUTTON_LEFT, x, y, zr_true);
|
||||
zr_input_motion(context, x, y);
|
||||
zr_input_end(context);
|
||||
zr_input_begin(context);
|
||||
zr_input_button(context, ZR_BUTTON_LEFT, x, y, zr_true);
|
||||
break;
|
||||
case 6:
|
||||
zr_input_button(&gui.ctx, ZR_BUTTON_LEFT, x, y, zr_false);
|
||||
zr_input_end(&gui.ctx);
|
||||
zr_input_button(context, ZR_BUTTON_LEFT, x, y, zr_false);
|
||||
zr_input_end(context);
|
||||
[self fillFrame];
|
||||
zr_clear(&gui.ctx);
|
||||
zr_input_begin(&gui.ctx);
|
||||
zr_input_motion(&gui.ctx, INT_MAX, INT_MAX);
|
||||
zr_clear(context);
|
||||
zr_input_begin(context);
|
||||
zr_input_motion(context, INT_MAX, INT_MAX);
|
||||
break;
|
||||
|
||||
#else
|
||||
|
||||
case 1: case 2: case 3: case 4:
|
||||
zr_input_motion(&gui.ctx, x, y);
|
||||
zr_input_motion(context, x, y);
|
||||
break;
|
||||
case 5:
|
||||
zr_input_button(&gui.ctx, ZR_BUTTON_LEFT, x, y, zr_true);
|
||||
zr_input_button(context, ZR_BUTTON_LEFT, x, y, zr_true);
|
||||
break;
|
||||
case 6:
|
||||
zr_input_button(&gui.ctx, ZR_BUTTON_LEFT, x, y, zr_false);
|
||||
zr_input_button(context, ZR_BUTTON_LEFT, x, y, zr_false);
|
||||
break;
|
||||
case 7:
|
||||
zr_input_button(&gui.ctx, ZR_BUTTON_RIGHT, x, y, zr_true);
|
||||
zr_input_button(context, ZR_BUTTON_RIGHT, x, y, zr_true);
|
||||
break;
|
||||
case 8:
|
||||
zr_input_button(&gui.ctx, ZR_BUTTON_RIGHT, x, y, zr_false);
|
||||
zr_input_button(context, ZR_BUTTON_RIGHT, x, y, zr_false);
|
||||
break;
|
||||
case 9:
|
||||
zr_input_button(&gui.ctx, ZR_BUTTON_MIDDLE, x, y, zr_true);
|
||||
zr_input_button(context, ZR_BUTTON_MIDDLE, x, y, zr_true);
|
||||
break;
|
||||
case 10:
|
||||
zr_input_button(&gui.ctx, ZR_BUTTON_MIDDLE, x, y, zr_false);
|
||||
zr_input_button(context, ZR_BUTTON_MIDDLE, x, y, zr_false);
|
||||
break;
|
||||
case 11:
|
||||
zr_input_scroll(&gui.ctx, -[event[@"deltaY"] floatValue]);
|
||||
zr_input_scroll(context, -[event[@"deltaY"] floatValue]);
|
||||
break;
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
|
||||
#endif
|
||||
|
||||
case 12:
|
||||
case 13:
|
||||
{
|
||||
@ -544,6 +607,29 @@ struct device
|
||||
NSData* data = [str dataUsingEncoding: NSUTF32LittleEndianStringEncoding];
|
||||
const uint32_t* c = data.bytes;
|
||||
NSInteger n = data.length / sizeof(uint32_t);
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
if (down)
|
||||
{
|
||||
if (n && *c == '\b')
|
||||
{
|
||||
zr_input_key(context, ZR_KEY_BACKSPACE, zr_true);
|
||||
zr_input_end(context);
|
||||
[self fillFrame];
|
||||
zr_clear(context);
|
||||
zr_input_begin(context);
|
||||
zr_input_key(context, ZR_KEY_BACKSPACE, zr_false);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (NSInteger i = 0; i < n; i += 1, c += 1)
|
||||
zr_input_unicode(context, *c);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
for (NSInteger i = 0; i < n; i += 1, c += 1)
|
||||
{
|
||||
if (*c == 127 || *c < ' ' || *c >= NSUpArrowFunctionKey)
|
||||
@ -551,28 +637,28 @@ struct device
|
||||
switch (*c)
|
||||
{
|
||||
case NSLeftArrowFunctionKey:
|
||||
zr_input_key(&gui.ctx, ZR_KEY_LEFT, down);
|
||||
zr_input_key(context, ZR_KEY_LEFT, down);
|
||||
break;
|
||||
case NSRightArrowFunctionKey:
|
||||
zr_input_key(&gui.ctx, ZR_KEY_RIGHT, down);
|
||||
zr_input_key(context, ZR_KEY_RIGHT, down);
|
||||
break;
|
||||
case 3:
|
||||
zr_input_key(&gui.ctx, ZR_KEY_COPY, down);
|
||||
zr_input_key(context, ZR_KEY_COPY, down);
|
||||
break;
|
||||
case 22:
|
||||
zr_input_key(&gui.ctx, ZR_KEY_PASTE, down);
|
||||
zr_input_key(context, ZR_KEY_PASTE, down);
|
||||
break;
|
||||
case 24:
|
||||
zr_input_key(&gui.ctx, ZR_KEY_CUT, down);
|
||||
zr_input_key(context, ZR_KEY_CUT, down);
|
||||
break;
|
||||
case 9:
|
||||
zr_input_key(&gui.ctx, ZR_KEY_TAB, down);
|
||||
zr_input_key(context, ZR_KEY_TAB, down);
|
||||
break;
|
||||
case 13:
|
||||
zr_input_key(&gui.ctx, ZR_KEY_ENTER, down);
|
||||
zr_input_key(context, ZR_KEY_ENTER, down);
|
||||
break;
|
||||
case 127:
|
||||
zr_input_key(&gui.ctx, ZR_KEY_BACKSPACE, down);
|
||||
zr_input_key(context, ZR_KEY_BACKSPACE, down);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -580,28 +666,80 @@ struct device
|
||||
}
|
||||
else if (down)
|
||||
{
|
||||
zr_input_unicode(&gui.ctx, *c);
|
||||
zr_input_unicode(context, *c);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
zr_input_end(&gui.ctx);
|
||||
zr_input_end(context);
|
||||
}
|
||||
|
||||
|
||||
- (void) addEvent: (NSDictionary*) event
|
||||
{
|
||||
[drawCommands removeAllObjects];
|
||||
[bufferedCommands removeAllObjects];
|
||||
[events addObject: event];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@protocol ZahnradKeyboardDelegate <NSObject>
|
||||
|
||||
- (void) showKeyboard: (NSDictionary*) info;
|
||||
- (void) hideKeyboard;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
|
||||
void zr_backend_show_keyboard(zr_hash zrHash, struct zr_rect zrBounds, struct zr_buffer* zrText)
|
||||
{
|
||||
CGRect frame = CGRectMake(zrBounds.x, zrBounds.y, zrBounds.w, zrBounds.h);
|
||||
id ad = [[UIApplication sharedApplication] delegate];
|
||||
if ([ad respondsToSelector: @selector(showKeyboard:)])
|
||||
{
|
||||
char str[zrText->allocated + 1];
|
||||
strncpy(str, zrText->memory.ptr, zrText->allocated);
|
||||
str[zrText->allocated] = 0;
|
||||
NSString* text = [NSString stringWithCString: str encoding: NSUTF8StringEncoding];
|
||||
[ad performSelector: @selector(showKeyboard:) withObject: @{@"hash" : @(zrHash), @"text" : text, @"frame" : NSStringFromCGRect(frame)}];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void zr_backend_hide_keyboard(void)
|
||||
{
|
||||
id ad = [[UIApplication sharedApplication] delegate];
|
||||
if ([ad respondsToSelector: @selector(hideKeyboard)])
|
||||
[ad performSelector: @selector(hideKeyboard)];
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
void zr_backend_show_keyboard(zr_hash zrHash, struct zr_rect zrBounds)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void zr_backend_hide_keyboard(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -7,13 +7,13 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
500B1FFA1C4B410F0002B53F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 500B1FF91C4B410F0002B53F /* main.m */; };
|
||||
500B20321C4B42B60002B53F /* ZahnradBackend.m in Sources */ = {isa = PBXBuildFile; fileRef = 500B20311C4B42B60002B53F /* ZahnradBackend.m */; };
|
||||
500B20341C4B43010002B53F /* zahnrad.c in Sources */ = {isa = PBXBuildFile; fileRef = 500B20331C4B43010002B53F /* zahnrad.c */; };
|
||||
500B203A1C4B43380002B53F /* DroidSans.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20361C4B43380002B53F /* DroidSans.ttf */; };
|
||||
500B203B1C4B43380002B53F /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20371C4B43380002B53F /* Roboto-Bold.ttf */; };
|
||||
500B203C1C4B43380002B53F /* Roboto-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20381C4B43380002B53F /* Roboto-Light.ttf */; };
|
||||
500B203D1C4B43380002B53F /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 500B20391C4B43380002B53F /* Roboto-Regular.ttf */; };
|
||||
504DFDF11C4EA36500D3714A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 500B1FF91C4B410F0002B53F /* main.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@ -27,6 +27,8 @@
|
||||
500B20371C4B43380002B53F /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Bold.ttf"; sourceTree = "<group>"; };
|
||||
500B20381C4B43380002B53F /* Roboto-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Light.ttf"; sourceTree = "<group>"; };
|
||||
500B20391C4B43380002B53F /* Roboto-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Regular.ttf"; sourceTree = "<group>"; };
|
||||
504DFDEB1C4EA2EE00D3714A /* zahnrad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = zahnrad.h; path = ../../../zahnrad.h; sourceTree = "<group>"; };
|
||||
504DFDEF1C4EA36200D3714A /* demo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = demo.c; path = ../../demo.c; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -60,9 +62,11 @@
|
||||
500B1FF71C4B410F0002B53F /* iOS_GL_ES */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
504DFDEF1C4EA36200D3714A /* demo.c */,
|
||||
500B20301C4B42B60002B53F /* ZahnradBackend.h */,
|
||||
500B20311C4B42B60002B53F /* ZahnradBackend.m */,
|
||||
500B1FF91C4B410F0002B53F /* main.m */,
|
||||
504DFDEB1C4EA2EE00D3714A /* zahnrad.h */,
|
||||
500B20331C4B43010002B53F /* zahnrad.c */,
|
||||
500B200D1C4B410F0002B53F /* Info.plist */,
|
||||
);
|
||||
@ -152,8 +156,8 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
500B1FFA1C4B410F0002B53F /* main.m in Sources */,
|
||||
500B20341C4B43010002B53F /* zahnrad.c in Sources */,
|
||||
504DFDF11C4EA36500D3714A /* main.m in Sources */,
|
||||
500B20321C4B42B60002B53F /* ZahnradBackend.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -24,12 +24,15 @@
|
||||
#import "ZahnradBackend.h"
|
||||
|
||||
|
||||
@interface GameViewController : GLKViewController
|
||||
@interface GameViewController : GLKViewController <UIKeyInput>
|
||||
@end
|
||||
|
||||
|
||||
@implementation GameViewController
|
||||
{
|
||||
BOOL keyboardAllowed;
|
||||
NSUInteger keyboardHash;
|
||||
|
||||
EAGLContext* context;
|
||||
ZahnradBackend* zr;
|
||||
}
|
||||
@ -39,6 +42,8 @@
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
keyboardHash = -1;
|
||||
|
||||
context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES3];
|
||||
assert(context != nil);
|
||||
|
||||
@ -110,6 +115,58 @@
|
||||
}
|
||||
|
||||
|
||||
- (void) insertText: (NSString*) text
|
||||
{
|
||||
[zr addEvent: @{@"type" : @12, @"txt" : text, @"mod" : @0}];
|
||||
}
|
||||
|
||||
|
||||
- (void) deleteBackward
|
||||
{
|
||||
[zr addEvent: @{@"type" : @12, @"txt" : @"\b", @"mod" : @0}];
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) hasText
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) canBecomeFirstResponder
|
||||
{
|
||||
return keyboardAllowed;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) canResignFirstResponder
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
- (void) showKeyboard: (NSDictionary*) info
|
||||
{
|
||||
NSUInteger hash = [info[@"hash"] unsignedIntegerValue];
|
||||
|
||||
if (hash != keyboardHash)
|
||||
{
|
||||
keyboardHash = hash;
|
||||
keyboardAllowed = YES;
|
||||
if (!self.isFirstResponder)
|
||||
[self becomeFirstResponder];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) hideKeyboard
|
||||
{
|
||||
keyboardHash = -1;
|
||||
keyboardAllowed = NO;
|
||||
[self resignFirstResponder];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -119,6 +176,7 @@
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow* window;
|
||||
@property (strong, nonatomic) GameViewController* gameViewController;
|
||||
|
||||
@end
|
||||
|
||||
@ -126,10 +184,27 @@
|
||||
@implementation AppDelegate
|
||||
|
||||
|
||||
- (void) showKeyboard: (NSDictionary*) info
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.gameViewController showKeyboard: info];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
- (void) hideKeyboard
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.gameViewController hideKeyboard];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) application: (UIApplication*) application didFinishLaunchingWithOptions: (NSDictionary*) launchOptions
|
||||
{
|
||||
_window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
|
||||
_window.rootViewController = [GameViewController new];
|
||||
_gameViewController = [GameViewController new];
|
||||
_window.rootViewController = _gameViewController;
|
||||
[_window makeKeyAndVisible];
|
||||
|
||||
return YES;
|
||||
|
@ -27,6 +27,8 @@
|
||||
500B208F1C4B4D700002B53F /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Bold.ttf"; sourceTree = "<group>"; };
|
||||
500B20901C4B4D700002B53F /* Roboto-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Light.ttf"; sourceTree = "<group>"; };
|
||||
500B20911C4B4D700002B53F /* Roboto-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Regular.ttf"; sourceTree = "<group>"; };
|
||||
504DFDEC1C4EA2FF00D3714A /* zahnrad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = zahnrad.h; path = ../../../zahnrad.h; sourceTree = "<group>"; };
|
||||
504DFDF21C4EA37700D3714A /* demo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = demo.c; path = ../../demo.c; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -60,9 +62,11 @@
|
||||
500B20631C4B4AB00002B53F /* tvOS_GL_ES */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
504DFDF21C4EA37700D3714A /* demo.c */,
|
||||
500B20881C4B4D460002B53F /* ZahnradBackend.h */,
|
||||
500B20891C4B4D460002B53F /* ZahnradBackend.m */,
|
||||
500B20651C4B4AB00002B53F /* main.m */,
|
||||
504DFDEC1C4EA2FF00D3714A /* zahnrad.h */,
|
||||
500B208B1C4B4D580002B53F /* zahnrad.c */,
|
||||
500B20741C4B4AB00002B53F /* Info.plist */,
|
||||
);
|
||||
|
@ -24,17 +24,21 @@
|
||||
#import "ZahnradBackend.h"
|
||||
|
||||
|
||||
@interface GameViewController : GLKViewController
|
||||
@interface GameViewController : GLKViewController <UITextFieldDelegate>
|
||||
@end
|
||||
|
||||
|
||||
@implementation GameViewController
|
||||
{
|
||||
EAGLContext* context;
|
||||
ZahnradBackend* zr;
|
||||
|
||||
NSUInteger keyboardHash;
|
||||
UITextField* textInputField;
|
||||
|
||||
CGPoint cursor;
|
||||
UIView* cursorView;
|
||||
|
||||
EAGLContext* context;
|
||||
ZahnradBackend* zr;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -42,6 +46,8 @@
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
keyboardHash = -1;
|
||||
|
||||
context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES3];
|
||||
assert(context != nil);
|
||||
|
||||
@ -53,10 +59,14 @@
|
||||
|
||||
UIPanGestureRecognizer* panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action: @selector(pan:)];
|
||||
[self.view addGestureRecognizer:panRecognizer];
|
||||
|
||||
cursorView = [[UIView alloc] initWithFrame: CGRectMake(100, 100, 10, 10)];
|
||||
cursorView.backgroundColor = UIColor.redColor;
|
||||
[self.view addSubview: cursorView];
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
cursor = CGPointMake(95, 70);
|
||||
cursorView = [[UIView alloc] initWithFrame: CGRectMake(cursor.x, cursor.y, 10, 10)];
|
||||
cursorView.backgroundColor = UIColor.redColor;
|
||||
[self.view addSubview: cursorView];
|
||||
[zr addEvent: @{@"type" : @2, @"pos" : NSStringFromCGPoint(cursor)}];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -85,8 +95,23 @@
|
||||
{
|
||||
CGPoint delta = [panRecognizer translationInView: self.view];
|
||||
|
||||
cursor.x += delta.x / 33.0;
|
||||
cursor.y += delta.y / 33.0;
|
||||
#if 0
|
||||
|
||||
CGFloat s = 33.0;
|
||||
|
||||
cursor.x += delta.x / s;
|
||||
cursor.y += delta.y / s;
|
||||
|
||||
#else
|
||||
|
||||
CGFloat s = 150.0;
|
||||
|
||||
if (delta.x != 0.0)
|
||||
cursor.x += pow(2.0, fabs(delta.x / s)) * (delta.x > 0.0 ? 1.0 : -1.0);
|
||||
if (delta.y != 0.0)
|
||||
cursor.y += pow(2.0, fabs(delta.y / s)) * (delta.y > 0.0 ? 1.0 : -1.0);
|
||||
#endif
|
||||
|
||||
|
||||
CGRect bounds = self.view.bounds;
|
||||
if (cursor.x < CGRectGetMinX(bounds)) cursor.x = CGRectGetMinX(bounds);
|
||||
@ -95,7 +120,7 @@
|
||||
if (cursor.y > CGRectGetMaxY(bounds)) cursor.y = CGRectGetMaxY(bounds);
|
||||
|
||||
cursorView.center = cursor;
|
||||
|
||||
|
||||
[zr addEvent: @{@"type" : @2, @"pos" : NSStringFromCGPoint(cursor)}];
|
||||
}
|
||||
|
||||
@ -124,6 +149,53 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (BOOL) textFieldShouldReturn: (UITextField*) textField
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
- (void) textFieldDidEndEditing: (UITextField*) textField
|
||||
{
|
||||
[textInputField resignFirstResponder];
|
||||
[textInputField removeFromSuperview];
|
||||
textInputField = nil;
|
||||
|
||||
[zr addEvent: @{@"type" : @12, @"txt" : textField.text, @"mod" : @0}];
|
||||
}
|
||||
|
||||
|
||||
- (void) showKeyboard: (NSDictionary*) info
|
||||
{
|
||||
NSUInteger hash = [info[@"hash"] unsignedIntegerValue];
|
||||
|
||||
if (hash != keyboardHash)
|
||||
{
|
||||
keyboardHash = hash;
|
||||
if (!textInputField)
|
||||
{
|
||||
CGRect frame = CGRectFromString(info[@"frame"]);
|
||||
textInputField = [[UITextField alloc] initWithFrame: frame];
|
||||
textInputField.delegate = self;
|
||||
textInputField.text = info[@"text"];
|
||||
[self.view addSubview: textInputField];
|
||||
[textInputField becomeFirstResponder];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) hideKeyboard
|
||||
{
|
||||
[textInputField resignFirstResponder];
|
||||
[textInputField removeFromSuperview];
|
||||
textInputField = nil;
|
||||
|
||||
keyboardHash = -1;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -133,6 +205,7 @@
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow* window;
|
||||
@property (strong, nonatomic) GameViewController* gameViewController;
|
||||
|
||||
@end
|
||||
|
||||
@ -140,10 +213,27 @@
|
||||
@implementation AppDelegate
|
||||
|
||||
|
||||
- (void) showKeyboard: (NSDictionary*) info
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.gameViewController showKeyboard: info];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
- (void) hideKeyboard
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.gameViewController hideKeyboard];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) application: (UIApplication*) application didFinishLaunchingWithOptions: (NSDictionary*) launchOptions
|
||||
{
|
||||
_window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
|
||||
_window.rootViewController = [GameViewController new];
|
||||
_gameViewController = [GameViewController new];
|
||||
_window.rootViewController = _gameViewController;
|
||||
[_window makeKeyAndVisible];
|
||||
|
||||
return YES;
|
||||
|
Loading…
Reference in New Issue
Block a user