mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-29 05:08:36 +01:00
Merge branch 'master' of github.com:hrydgard/native
This commit is contained in:
commit
ee2dfaba5a
76 files changed
+3227
-2291
No files matched your search
+17
-6
@@ -20,9 +20,10 @@
|
||||
#include "file/zip_read.h"
|
||||
#include "input/input_state.h"
|
||||
#include "audio/mixer.h"
|
||||
#include "math/math_util.h"
|
||||
|
||||
#define coord_xres 800
|
||||
#define coord_yres 480
|
||||
#define coord_xres 480
|
||||
#define coord_yres 800
|
||||
|
||||
static JNIEnv *jniEnvUI;
|
||||
|
||||
@@ -97,6 +98,13 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init
|
||||
yres = yyres;
|
||||
g_xres = xres;
|
||||
g_yres = yres;
|
||||
|
||||
if (g_xres < g_yres)
|
||||
{
|
||||
// Portrait - let's force the imaginary resolution we want
|
||||
g_xres = coord_xres;
|
||||
g_yres = coord_yres;
|
||||
}
|
||||
xscale = (float)coord_xres / xres;
|
||||
yscale = (float)coord_yres / yres;
|
||||
memset(&input_state, 0, sizeof(input_state));
|
||||
@@ -189,6 +197,9 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender
|
||||
}
|
||||
|
||||
extern "C" void Java_com_turboviking_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) {
|
||||
// The audio thread can pretty safely enable Flush-to-Zero mode on the FPU.
|
||||
EnableFZ();
|
||||
|
||||
int buf_size = env->GetArrayLength(array);
|
||||
if (buf_size) {
|
||||
short *data = env->GetShortArrayElements(array, 0);
|
||||
@@ -207,14 +218,14 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch
|
||||
return; // We ignore 8+ pointers entirely.
|
||||
}
|
||||
|
||||
input_state.mouse_x[pointerId] = (int)x;
|
||||
input_state.mouse_y[pointerId] = (int)y;
|
||||
input_state.mouse_x[pointerId] = (int)(x * xscale);
|
||||
input_state.mouse_y[pointerId] = (int)(y * yscale);
|
||||
if (code == 1) {
|
||||
ILOG("Down: %i %f %f", pointerId, x, y);
|
||||
//ILOG("Down: %i %f %f", pointerId, x, y);
|
||||
input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId];
|
||||
input_state.mouse_down[pointerId] = true;
|
||||
} else if (code == 2) {
|
||||
ILOG("Up: %i %f %f", pointerId, x, y);
|
||||
//ILOG("Up: %i %f %f", pointerId, x, y);
|
||||
input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId];
|
||||
input_state.mouse_down[pointerId] = false;
|
||||
}
|
||||
|
||||
@@ -16,4 +16,4 @@ public class NativeApp {
|
||||
// Sensor/input data. These are asynchronous, beware!
|
||||
public static native void touch(float x, float y, int data, int pointerId);
|
||||
public static native void accelerometer(float x, float y, float z);
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ public class NativeAudioPlayer {
|
||||
playThread();
|
||||
}
|
||||
});
|
||||
thread.setPriority(Thread.MAX_PRIORITY);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
||||
+26
-21
@@ -33,7 +33,7 @@ struct Clip {
|
||||
|
||||
// If current_clip == 0, the channel is free.
|
||||
|
||||
enum PlaybackState {
|
||||
enum ClipPlaybackState {
|
||||
PB_STOPPED = 0,
|
||||
PB_PLAYING = 1,
|
||||
};
|
||||
@@ -42,7 +42,7 @@ enum PlaybackState {
|
||||
struct Channel {
|
||||
const Clip *current_clip;
|
||||
// Playback state
|
||||
PlaybackState state;
|
||||
ClipPlaybackState state;
|
||||
int pos;
|
||||
PlayParams params;
|
||||
// Effect state
|
||||
@@ -89,26 +89,26 @@ static int get_free_channel(Mixer *mixer) {
|
||||
}
|
||||
|
||||
Clip *clip_load(const char *filename) {
|
||||
short *data;
|
||||
short *data;
|
||||
int num_samples, sample_rate, num_channels;
|
||||
|
||||
if (!strcmp(filename + strlen(filename) - 4, ".ogg")) {
|
||||
// Ogg file. For now, directly decompress, no streaming support.
|
||||
uint8_t *filedata;
|
||||
size_t size;
|
||||
filedata = VFSReadFile(filename, &size);
|
||||
num_samples = stb_vorbis_decode_memory(filedata, size, &num_channels, &data);
|
||||
if (num_samples <= 0)
|
||||
return NULL;
|
||||
sample_rate = 44100;
|
||||
ILOG("read ogg %s, length %i, rate %i", filename, num_samples, sample_rate);
|
||||
} else {
|
||||
// Wav file. Easy peasy.
|
||||
data = wav_read(filename, &num_samples, &sample_rate, &num_channels);
|
||||
if (!data) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (!strcmp(filename + strlen(filename) - 4, ".ogg")) {
|
||||
// Ogg file. For now, directly decompress, no streaming support.
|
||||
uint8_t *filedata;
|
||||
size_t size;
|
||||
filedata = VFSReadFile(filename, &size);
|
||||
num_samples = stb_vorbis_decode_memory(filedata, size, &num_channels, &data);
|
||||
if (num_samples <= 0)
|
||||
return NULL;
|
||||
sample_rate = 44100;
|
||||
ILOG("read ogg %s, length %i, rate %i", filename, num_samples, sample_rate);
|
||||
} else {
|
||||
// Wav file. Easy peasy.
|
||||
data = wav_read(filename, &num_samples, &sample_rate, &num_channels);
|
||||
if (!data) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Clip *clip = new Clip();
|
||||
clip->type = CT_PCM16;
|
||||
@@ -130,7 +130,12 @@ void clip_destroy(Clip *clip) {
|
||||
}
|
||||
}
|
||||
|
||||
int clip_length(const Clip *clip) {
|
||||
const short *clip_data(const Clip *clip)
|
||||
{
|
||||
return clip->data;
|
||||
}
|
||||
|
||||
size_t clip_length(const Clip *clip) {
|
||||
return clip->length;
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
// Simple mixer intended for sound effects for games.
|
||||
// Intended both for fire and forget sfx (auto channels) and for
|
||||
// realtime-modifiable sounds like pitched engine noises (fixed channels).
|
||||
// The clip loading code supports ogg SFX.
|
||||
|
||||
struct Mixer;
|
||||
struct Clip;
|
||||
@@ -30,7 +31,8 @@ void mixer_mix(Mixer *mixer, short *buffer, int num_samples);
|
||||
Clip *clip_load(const char *filename);
|
||||
void clip_destroy(Clip *clip);
|
||||
|
||||
int clip_length();
|
||||
const short *clip_data(const Clip *clip);
|
||||
size_t clip_length(const Clip *clip);
|
||||
void clip_set_loop(int start, int end);
|
||||
|
||||
|
||||
|
||||
+6
-8
@@ -4,8 +4,9 @@
|
||||
#include "file/chunk_file.h"
|
||||
|
||||
short *wav_read(const char *filename,
|
||||
int *num_samples, int *sample_rate,
|
||||
int *num_channels) {
|
||||
int *num_samples, int *sample_rate,
|
||||
int *num_channels)
|
||||
{
|
||||
ChunkFile cf(filename, true);
|
||||
if (cf.failed()) {
|
||||
WLOG("ERROR: Wave file %s could not be opened", filename);
|
||||
@@ -16,10 +17,8 @@ short *wav_read(const char *filename,
|
||||
int samplesPerSec, avgBytesPerSec,wBlockAlign,wBytesPerSample;
|
||||
if (cf.descend('RIFF')) {
|
||||
cf.readInt(); //get past 'WAVE'
|
||||
if (cf.descend('fmt ')) //enter the format chunk
|
||||
{
|
||||
int temp;
|
||||
temp = cf.readInt();
|
||||
if (cf.descend('fmt ')) { //enter the format chunk
|
||||
int temp = cf.readInt();
|
||||
int format = temp & 0xFFFF;
|
||||
if (format != 1) {
|
||||
cf.ascend();
|
||||
@@ -42,8 +41,7 @@ short *wav_read(const char *filename,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cf.descend('data')) //enter the data chunk
|
||||
{
|
||||
if (cf.descend('data')) { //enter the data chunk
|
||||
int numBytes = cf.getCurrentChunkSize();
|
||||
int numSamples = numBytes / wBlockAlign;
|
||||
data = (short *)malloc(sizeof(short) * numSamples * *num_channels);
|
||||
|
||||
+2
-1
@@ -2,7 +2,8 @@ set(SRCS
|
||||
LAMEString.cpp
|
||||
colorutil.cpp
|
||||
error_context.cpp
|
||||
display.cpp)
|
||||
display.cpp
|
||||
buffer.cpp)
|
||||
|
||||
set(SRCS ${SRCS})
|
||||
|
||||
|
||||
+3
-2
@@ -1,6 +1,7 @@
|
||||
// NOTE: This is only here for legacy reasons.
|
||||
// In new code, please use std::string.
|
||||
// DEPRECATED
|
||||
|
||||
// This is only here for legacy reasons.
|
||||
// In new code, please use std::string.
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
+18
-5
@@ -23,6 +23,7 @@
|
||||
#include "file/zip_read.h"
|
||||
#include "input/input_state.h"
|
||||
#include "base/NativeApp.h"
|
||||
#include "net/resolve.h"
|
||||
|
||||
|
||||
// Simple implementations of System functions
|
||||
@@ -131,10 +132,14 @@ int main(int argc, char *argv[]) {
|
||||
g_xres = 800;
|
||||
g_yres = 480;
|
||||
} else {
|
||||
g_xres = 1480;
|
||||
g_yres = 800;
|
||||
#ifdef _WIN32
|
||||
g_xres = 1580;
|
||||
g_yres = 1000;
|
||||
#endif
|
||||
}
|
||||
|
||||
net::Init();
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
|
||||
return 1;
|
||||
@@ -208,13 +213,15 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
InputState input_state;
|
||||
int framecount = 0;
|
||||
|
||||
bool nextFrameMD = 0;
|
||||
while (true) {
|
||||
SDL_Event event;
|
||||
|
||||
input_state.accelerometer_valid = false;
|
||||
input_state.mouse_valid = true;
|
||||
int done = 0;
|
||||
|
||||
// input_state.mouse_down[1] = nextFrameMD;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
done = 1;
|
||||
@@ -225,19 +232,25 @@ int main(int argc, char *argv[]) {
|
||||
} else if (event.type == SDL_MOUSEMOTION) {
|
||||
input_state.mouse_x[0] = event.motion.x;
|
||||
input_state.mouse_y[0] = event.motion.y;
|
||||
input_state.mouse_x[1] = event.motion.x + 150;
|
||||
input_state.mouse_y[1] = event.motion.y;
|
||||
} else if (event.type == SDL_MOUSEBUTTONDOWN) {
|
||||
if (event.button.button == SDL_BUTTON_LEFT) {
|
||||
///input_state.mouse_buttons_down = 1;
|
||||
input_state.mouse_down[0] = true;
|
||||
input_state.mouse_down[0] = true;
|
||||
nextFrameMD = true;
|
||||
}
|
||||
} else if (event.type == SDL_MOUSEBUTTONUP) {
|
||||
if (event.button.button == SDL_BUTTON_LEFT) {
|
||||
input_state.mouse_down[0] = false;
|
||||
input_state.mouse_down[0] = false;
|
||||
nextFrameMD = false;
|
||||
//input_state.mouse_buttons_up = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (done) break;
|
||||
|
||||
input_state.mouse_last[0] = input_state.mouse_down[0];
|
||||
|
||||
@@ -31,6 +31,8 @@ typedef int64_t int64;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
typedef intptr_t ssize_t;
|
||||
|
||||
#include <tchar.h>
|
||||
|
||||
#define ALIGNED16(x) __declspec(align(16)) x
|
||||
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
#include "base/buffer.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#undef min
|
||||
#undef max
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "file/fd_util.h"
|
||||
|
||||
Buffer::Buffer() { }
|
||||
Buffer::~Buffer() { }
|
||||
|
||||
char *Buffer::Append(ssize_t length) {
|
||||
size_t old_size = data_.size();
|
||||
data_.resize(old_size + length);
|
||||
return &data_[0] + old_size;
|
||||
}
|
||||
|
||||
void Buffer::Append(const std::string &str) {
|
||||
char *ptr = Append(str.size());
|
||||
memcpy(ptr, str.data(), str.size());
|
||||
}
|
||||
|
||||
void Buffer::Append(const char *str) {
|
||||
size_t len = strlen(str);
|
||||
char *dest = Append(len);
|
||||
memcpy(dest, str, len);
|
||||
}
|
||||
|
||||
void Buffer::AppendValue(int value) {
|
||||
char buf[16];
|
||||
// This is slow.
|
||||
sprintf(buf, "%i", value);
|
||||
Append(buf);
|
||||
}
|
||||
|
||||
void Buffer::Take(size_t length, std::string *dest) {
|
||||
CHECK_LE(length, data_.size());
|
||||
dest->resize(length);
|
||||
memcpy(&(*dest)[0], &data_[0], length);
|
||||
data_.erase(data_.begin(), data_.begin() + length);
|
||||
}
|
||||
|
||||
int Buffer::TakeLineCRLF(std::string *dest) {
|
||||
int after_next_line = OffsetToAfterNextCRLF();
|
||||
if (after_next_line < 0)
|
||||
return after_next_line;
|
||||
else {
|
||||
Take(after_next_line - 2, dest);
|
||||
Skip(2); // Skip the CRLF
|
||||
return after_next_line - 2;
|
||||
}
|
||||
}
|
||||
|
||||
void Buffer::Skip(size_t length) {
|
||||
data_.erase(data_.begin(), data_.begin() + length);
|
||||
}
|
||||
|
||||
int Buffer::SkipLineCRLF() {
|
||||
int after_next_line = OffsetToAfterNextCRLF();
|
||||
if (after_next_line < 0)
|
||||
return after_next_line;
|
||||
else {
|
||||
Skip(after_next_line);
|
||||
return after_next_line - 2;
|
||||
}
|
||||
}
|
||||
|
||||
int Buffer::OffsetToAfterNextCRLF() {
|
||||
for (size_t i = 0; i < data_.size() - 1; i++) {
|
||||
if (data_[i] == '\r' && data_[i + 1] == '\n') {
|
||||
return i + 2;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Buffer::Printf(const char *fmt, ...) {
|
||||
char buffer[512];
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
ssize_t retval = vsnprintf(buffer, sizeof(buffer), fmt, vl);
|
||||
if (retval >= (ssize_t)sizeof(buffer)) {
|
||||
// Output was truncated. TODO: Do something.
|
||||
FLOG("Buffer::Printf truncated output");
|
||||
}
|
||||
CHECK_GE(retval, 0);
|
||||
va_end(vl);
|
||||
char *ptr = Append(retval);
|
||||
CHECK(ptr);
|
||||
memcpy(ptr, buffer, retval);
|
||||
}
|
||||
|
||||
bool Buffer::Flush(int fd) {
|
||||
// Look into using send() directly.
|
||||
bool success = (ssize_t)data_.size() == fd_util::WriteLine(fd, &data_[0], data_.size());
|
||||
if (success) {
|
||||
data_.resize(0);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Buffer::FlushSocket(uintptr_t sock) {
|
||||
// TODO: send may need retries!
|
||||
size_t sent = send(sock, &data_[0], data_.size(), 0);
|
||||
// bool success = fd_util::WriteLine(fd, data_.data(), data_.size());
|
||||
if (sent == data_.size()) {
|
||||
data_.resize(0);
|
||||
return true;
|
||||
} else {
|
||||
ELOG("FlushSocket failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Buffer::ReadAll(int fd) {
|
||||
char buf[1024];
|
||||
int retval;
|
||||
while ((retval = recv(fd, buf, sizeof(buf), 0)) > 0) {
|
||||
char *p = Append((size_t)retval);
|
||||
memcpy(p, buf, retval);
|
||||
}
|
||||
}
|
||||
|
||||
void Buffer::Read(int fd, size_t sz) {
|
||||
char buf[1024];
|
||||
int retval;
|
||||
while ((retval = recv(fd, buf, std::min(sz, sizeof(buf)), 0)) > 0) {
|
||||
char *p = Append((size_t)retval);
|
||||
memcpy(p, buf, retval);
|
||||
sz -= retval;
|
||||
if (sz == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Buffer::PeekAll(std::string *dest) {
|
||||
dest->resize(data_.size());
|
||||
memcpy(&(*dest)[0], &data_[0], data_.size());
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#ifndef _IO_BUFFER_H
|
||||
#define _IO_BUFFER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/logging.h"
|
||||
|
||||
// Acts as a queue. Intended to be as fast as possible for most uses.
|
||||
// Does not do synchronization, must use external mutexes.
|
||||
class Buffer {
|
||||
public:
|
||||
Buffer();
|
||||
~Buffer();
|
||||
|
||||
// Write max [length] bytes to the returned pointer.
|
||||
// Any other operation on this Buffer invalidates the pointer.
|
||||
char *Append(ssize_t length);
|
||||
char *Append(size_t length) { return Append((ssize_t)length); }
|
||||
|
||||
// These work pretty much like you'd expect.
|
||||
void Append(const char *str); // str null-terminated. The null is not copied.
|
||||
void Append(const std::string &str);
|
||||
|
||||
// Various types. Useful for varz etc. Appends a string representation of the
|
||||
// value, rather than a binary representation.
|
||||
void AppendValue(int value);
|
||||
|
||||
// Parsing Helpers
|
||||
|
||||
// Use for easy line skipping. If no CRLF within the buffer, returns -1.
|
||||
// If parsing HTML headers, this indicates that you should probably buffer up
|
||||
// more data.
|
||||
int OffsetToAfterNextCRLF();
|
||||
|
||||
// Takers
|
||||
|
||||
void Take(size_t length, std::string *dest);
|
||||
void TakeAll(std::string *dest) { Take(size(), dest); }
|
||||
// On failure, return value < 0 and *dest is unchanged.
|
||||
// Strips off the actual CRLF from the result.
|
||||
int TakeLineCRLF(std::string *dest);
|
||||
|
||||
// Skippers
|
||||
void Skip(size_t length);
|
||||
// Returns -1 on failure (no CRLF within sight).
|
||||
// Otherwise returns the length of the line skipped, not including CRLF. Can be 0.
|
||||
int SkipLineCRLF();
|
||||
|
||||
// Utility functions.
|
||||
void Printf(const char *fmt, ...);
|
||||
|
||||
// Dumps the entire buffer to the string, but keeps it around.
|
||||
// Only to be used for debugging, since it might not be fast at all.
|
||||
void PeekAll(std::string *dest);
|
||||
|
||||
// Simple I/O.
|
||||
|
||||
// Writes the entire buffer to the file descriptor. Also resets the
|
||||
// size to zero. On failure, data remains in buffer and nothing is
|
||||
// written.
|
||||
bool Flush(int fd);
|
||||
bool FlushSocket(uintptr_t sock); // Windows portability
|
||||
|
||||
void ReadAll(int fd);
|
||||
void Read(int fd, size_t sz);
|
||||
|
||||
// Utilities. Try to avoid checking for size.
|
||||
size_t size() const { return data_.size(); }
|
||||
bool empty() const { return size() == 0; }
|
||||
void clear() { data_.resize(0); }
|
||||
|
||||
private:
|
||||
// TODO: Find a better internal representation, like a cord.
|
||||
std::vector<char> data_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Buffer);
|
||||
};
|
||||
|
||||
#endif // _IO_BUFFER_H
|
||||
+78
-72
@@ -1,3 +1,47 @@
|
||||
#include "base/colorutil.h"
|
||||
|
||||
uint32_t whiteAlpha(float alpha) {
|
||||
if (alpha < 0.0f) alpha = 0.0f;
|
||||
if (alpha > 1.0f) alpha = 1.0f;
|
||||
uint32_t color = (int)(alpha*255) << 24;
|
||||
color |= 0xFFFFFF;
|
||||
return color;
|
||||
}
|
||||
|
||||
uint32_t blackAlpha(float alpha) {
|
||||
if (alpha < 0.0f) alpha = 0.0f;
|
||||
if (alpha > 1.0f) alpha = 1.0f;
|
||||
return (int)(alpha*255)<<24;
|
||||
}
|
||||
|
||||
uint32_t colorAlpha(uint32_t color, float alpha) {
|
||||
if (alpha < 0.0f) alpha = 0.0f;
|
||||
if (alpha > 1.0f) alpha = 1.0f;
|
||||
return ((int)(alpha*255)<<24) | (color & 0xFFFFFF);
|
||||
}
|
||||
|
||||
uint32_t rgba(float r, float g, float b, float alpha) {
|
||||
uint32_t color = (int)(alpha*255)<<24;
|
||||
color |= (int)(b*255)<<16;
|
||||
color |= (int)(g*255)<<8;
|
||||
color |= (int)(r*255);
|
||||
return color;
|
||||
}
|
||||
|
||||
uint32_t rgba_clamp(float r, float g, float b, float a) {
|
||||
if (r > 1.0f) r = 1.0f;
|
||||
if (g > 1.0f) g = 1.0f;
|
||||
if (b > 1.0f) b = 1.0f;
|
||||
if (a > 1.0f) a = 1.0f;
|
||||
|
||||
if (r < 0.0f) r = 0.0f;
|
||||
if (g < 0.0f) g = 0.0f;
|
||||
if (b < 0.0f) b = 0.0f;
|
||||
if (a < 0.0f) a = 0.0f;
|
||||
|
||||
return rgba(r,g,b,a);
|
||||
}
|
||||
|
||||
/* hsv2rgb.c
|
||||
* Convert Hue Saturation Value to Red Green Blue
|
||||
*
|
||||
@@ -8,79 +52,41 @@
|
||||
* Procedural Elements for Computer Graphics
|
||||
* McGraw Hill 1985
|
||||
*/
|
||||
|
||||
#include "base/colorutil.h"
|
||||
|
||||
uint32_t whiteAlpha(float alpha) {
|
||||
if (alpha < 0.0f) alpha = 0.0f;
|
||||
if (alpha > 1.0f) alpha = 1.0f;
|
||||
uint32_t color = (int)(alpha*255)<<24;
|
||||
color |= 0xFFFFFF;
|
||||
return color;
|
||||
}
|
||||
|
||||
uint32_t blackAlpha(float alpha) {
|
||||
if (alpha < 0.0f) alpha = 0.0f;
|
||||
if (alpha > 1.0f) alpha = 1.0f;
|
||||
return (int)(alpha*255)<<24;
|
||||
}
|
||||
|
||||
uint32_t rgba(float r, float g, float b, float alpha) {
|
||||
uint32_t color = (int)(alpha*255)<<24;
|
||||
color |= (int)(b*255)<<16;
|
||||
color |= (int)(g*255)<<8;
|
||||
color |= (int)(r*255);
|
||||
return color;
|
||||
}
|
||||
|
||||
uint32_t rgba_clamp(float r, float g, float b, float a) {
|
||||
if (r > 1.0f) r = 1.0f;
|
||||
if (g > 1.0f) g = 1.0f;
|
||||
if (b > 1.0f) b = 1.0f;
|
||||
if (a > 1.0f) a = 1.0f;
|
||||
|
||||
if (r < 0.0f) r = 0.0f;
|
||||
if (g < 0.0f) g = 0.0f;
|
||||
if (b < 0.0f) b = 0.0f;
|
||||
if (a < 0.0f) a = 0.0f;
|
||||
|
||||
return rgba(r,g,b,a);
|
||||
}
|
||||
|
||||
uint32_t hsva(float H, float S, float V, float alpha) {
|
||||
/*
|
||||
* Purpose:
|
||||
* Convert HSV values to RGB values
|
||||
* All values are in the range [0.0 .. 1.0]
|
||||
*/
|
||||
float F, M, N, K;
|
||||
int I;
|
||||
float r, g, b;
|
||||
if ( S == 0.0 ) {
|
||||
// Achromatic case, set level of grey
|
||||
return rgba(V, V, V, alpha);
|
||||
} else {
|
||||
/*
|
||||
* Determine levels of primary colours.
|
||||
*/
|
||||
if (H >= 1.0) {
|
||||
H = 0.0;
|
||||
} else {
|
||||
H = H * 6;
|
||||
}
|
||||
I = (int) H; /* should be in the range 0..5 */
|
||||
F = H - I; /* fractional part */
|
||||
/*
|
||||
* Purpose:
|
||||
* Convert HSV values to RGB values
|
||||
* All values are in the range [0.0 .. 1.0]
|
||||
*/
|
||||
float F, M, N, K;
|
||||
int I;
|
||||
if ( S == 0.0 ) {
|
||||
// Achromatic case, set level of grey
|
||||
return rgba(V, V, V, alpha);
|
||||
} else {
|
||||
/*
|
||||
* Determine levels of primary colours.
|
||||
*/
|
||||
if (H >= 1.0) {
|
||||
H = 0.0;
|
||||
} else {
|
||||
H = H * 6;
|
||||
}
|
||||
I = (int) H; /* should be in the range 0..5 */
|
||||
F = H - I; /* fractional part */
|
||||
|
||||
M = V * (1 - S);
|
||||
N = V * (1 - S * F);
|
||||
K = V * (1 - S * (1 - F));
|
||||
M = V * (1 - S);
|
||||
N = V * (1 - S * F);
|
||||
K = V * (1 - S * (1 - F));
|
||||
|
||||
if (I == 0) { r = V; g = K; b = M; }
|
||||
if (I == 1) { r = N; g = V; b = M; }
|
||||
if (I == 2) { r = M; g = V; b = K; }
|
||||
if (I == 3) { r = M; g = N; b = V; }
|
||||
if (I == 4) { r = K; g = M; b = V; }
|
||||
if (I == 5) { r = V; g = M; b = N; }
|
||||
return rgba(r, g, b, alpha);
|
||||
}
|
||||
float r, g, b;
|
||||
if (I == 0) { r = V; g = K; b = M; }
|
||||
else if (I == 1) { r = N; g = V; b = M; }
|
||||
else if (I == 2) { r = M; g = V; b = K; }
|
||||
else if (I == 3) { r = M; g = N; b = V; }
|
||||
else if (I == 4) { r = K; g = M; b = V; }
|
||||
else if (I == 5) { r = V; g = M; b = N; }
|
||||
else return 0;
|
||||
return rgba(r, g, b, alpha);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
uint32_t whiteAlpha(float alpha);
|
||||
uint32_t blackAlpha(float alpha);
|
||||
uint32_t colorAlpha(uint32_t color, float alpha);
|
||||
uint32_t rgba(float r, float g, float b, float alpha);
|
||||
uint32_t rgba_clamp(float r, float g, float b, float alpha);
|
||||
uint32_t hsva(float h, float s, float v, float alpha);
|
||||
+14
-14
@@ -13,12 +13,12 @@ __THREAD std::vector<const char *> *_error_context_name;
|
||||
__THREAD std::vector<const char *> *_error_context_data;
|
||||
|
||||
_ErrorContext::_ErrorContext(const char *name, const char *data) {
|
||||
if (!_error_context_name) {
|
||||
_error_context_name = new std::vector<const char *>();
|
||||
_error_context_data = new std::vector<const char *>();
|
||||
_error_context_name->reserve(16);
|
||||
_error_context_data->reserve(16);
|
||||
}
|
||||
if (!_error_context_name) {
|
||||
_error_context_name = new std::vector<const char *>();
|
||||
_error_context_data = new std::vector<const char *>();
|
||||
_error_context_name->reserve(16);
|
||||
_error_context_data->reserve(16);
|
||||
}
|
||||
_error_context_name->push_back(name);
|
||||
_error_context_data->push_back(data);
|
||||
}
|
||||
@@ -29,12 +29,12 @@ _ErrorContext::~_ErrorContext() {
|
||||
}
|
||||
|
||||
void _ErrorContext::Log(const char *message) {
|
||||
ILOG("EC: %s", message);
|
||||
for (size_t i = 0; i < _error_context_name->size(); i++) {
|
||||
if ((*_error_context_data)[i] != 0) {
|
||||
ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]);
|
||||
} else {
|
||||
ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]);
|
||||
}
|
||||
}
|
||||
ILOG("EC: %s", message);
|
||||
for (size_t i = 0; i < _error_context_name->size(); i++) {
|
||||
if ((*_error_context_data)[i] != 0) {
|
||||
ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]);
|
||||
} else {
|
||||
ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,11 @@
|
||||
class _ErrorContext
|
||||
{
|
||||
public:
|
||||
_ErrorContext(const char *name, const char *data = 0);
|
||||
~_ErrorContext();
|
||||
_ErrorContext(const char *name, const char *data = 0);
|
||||
~_ErrorContext();
|
||||
|
||||
// Logs the current context stack.
|
||||
static void Log(const char *message);
|
||||
// Logs the current context stack.
|
||||
static void Log(const char *message);
|
||||
};
|
||||
|
||||
#define ErrorContext(...) _ErrorContext __ec(__VA_ARGS__)
|
||||
|
||||
@@ -60,6 +60,13 @@ inline void Crash() {
|
||||
|
||||
#endif
|
||||
|
||||
#undef CHECK
|
||||
|
||||
#define CHECK(a) {if (!(a)) {FLOG("CHECK failed");}}
|
||||
#define CHECK_P(a, ...) {if (!(a)) {FLOG("CHECK failed: " __VA_ARGS__);}}
|
||||
#define CHECK_EQ(a, b) CHECK((a) == (b));
|
||||
#define CHECK_NE(a, b) CHECK((a) != (b));
|
||||
#define CHECK_GT(a, b) CHECK((a) > (b));
|
||||
#define CHECK_GE(a, b) CHECK((a) >= (b));
|
||||
#define CHECK_LT(a, b) CHECK((a) < (b));
|
||||
#define CHECK_LE(a, b) CHECK((a) <= (b));
|
||||
+26
-26
@@ -14,58 +14,58 @@
|
||||
|
||||
class recursive_mutex {
|
||||
#ifdef _WIN32
|
||||
typedef CRITICAL_SECTION mutexType;
|
||||
typedef CRITICAL_SECTION mutexType;
|
||||
#else
|
||||
typedef pthread_mutex_t mutexType;
|
||||
typedef pthread_mutex_t mutexType;
|
||||
#endif
|
||||
public:
|
||||
recursive_mutex() {
|
||||
recursive_mutex() {
|
||||
#ifdef _WIN32
|
||||
InitializeCriticalSection(&mut_);
|
||||
InitializeCriticalSection(&mut_);
|
||||
#else
|
||||
pthread_mutex_init(&mut_, NULL);
|
||||
pthread_mutex_init(&mut_, NULL);
|
||||
#endif
|
||||
}
|
||||
~recursive_mutex() {
|
||||
}
|
||||
~recursive_mutex() {
|
||||
#ifdef _WIN32
|
||||
DeleteCriticalSection(&mut_);
|
||||
DeleteCriticalSection(&mut_);
|
||||
#else
|
||||
pthread_mutex_destroy(&mut_);
|
||||
pthread_mutex_destroy(&mut_);
|
||||
#endif
|
||||
}
|
||||
bool trylock() {
|
||||
}
|
||||
bool trylock() {
|
||||
#ifdef _WIN32
|
||||
return TryEnterCriticalSection(&mut_) == TRUE;
|
||||
return TryEnterCriticalSection(&mut_) == TRUE;
|
||||
#else
|
||||
return pthread_mutex_trylock(&mut_) != EBUSY;
|
||||
return pthread_mutex_trylock(&mut_) != EBUSY;
|
||||
#endif
|
||||
}
|
||||
void lock() {
|
||||
}
|
||||
void lock() {
|
||||
#ifdef _WIN32
|
||||
EnterCriticalSection(&mut_);
|
||||
EnterCriticalSection(&mut_);
|
||||
#else
|
||||
pthread_mutex_lock(&mut_);
|
||||
pthread_mutex_lock(&mut_);
|
||||
#endif
|
||||
}
|
||||
void unlock() {
|
||||
}
|
||||
void unlock() {
|
||||
#ifdef _WIN32
|
||||
LeaveCriticalSection(&mut_);
|
||||
LeaveCriticalSection(&mut_);
|
||||
#else
|
||||
pthread_mutex_unlock(&mut_);
|
||||
pthread_mutex_unlock(&mut_);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
mutexType mut_;
|
||||
mutexType mut_;
|
||||
};
|
||||
|
||||
class lock_guard {
|
||||
public:
|
||||
lock_guard(recursive_mutex &mtx) : mtx_(mtx) {mtx_.lock();}
|
||||
~lock_guard() {mtx_.unlock();}
|
||||
lock_guard(recursive_mutex &mtx) : mtx_(mtx) {mtx_.lock();}
|
||||
~lock_guard() {mtx_.unlock();}
|
||||
|
||||
private:
|
||||
recursive_mutex &mtx_;
|
||||
recursive_mutex &mtx_;
|
||||
};
|
||||
|
||||
#undef p
|
||||
|
||||
+12
-12
@@ -4,26 +4,26 @@
|
||||
|
||||
template<class T>
|
||||
class scoped_ptr {
|
||||
public:
|
||||
public:
|
||||
scoped_ptr() : ptr_(0) {}
|
||||
scoped_ptr(T *p) : ptr_(p) {}
|
||||
~scoped_ptr() {
|
||||
delete ptr_;
|
||||
}
|
||||
void reset(T *p) {
|
||||
delete ptr_;
|
||||
delete ptr_;
|
||||
ptr_ = p;
|
||||
}
|
||||
T *release() {
|
||||
T *p = ptr_;
|
||||
ptr_ = 0;
|
||||
return p;
|
||||
}
|
||||
T *operator->() { return ptr_; }
|
||||
const T *operator->() const { return ptr_; }
|
||||
T *release() {
|
||||
T *p = ptr_;
|
||||
ptr_ = 0;
|
||||
return p;
|
||||
}
|
||||
T *operator->() { return ptr_; }
|
||||
const T *operator->() const { return ptr_; }
|
||||
|
||||
private:
|
||||
scoped_ptr(const scoped_ptr<T> &other);
|
||||
void operator=(const scoped_ptr<T> &other);
|
||||
private:
|
||||
scoped_ptr(const scoped_ptr<T> &other);
|
||||
void operator=(const scoped_ptr<T> &other);
|
||||
T *ptr_;
|
||||
};
|
||||
+13
-1
@@ -1,9 +1,11 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "base/buffer.h"
|
||||
#include "base/stringutil.h"
|
||||
|
||||
unsigned int parseHex(const char *_szValue)
|
||||
{
|
||||
DWORD Count, Value = 0;
|
||||
int Count, Value = 0;
|
||||
size_t Finish = strlen(_szValue);
|
||||
if (Finish > 8 ) { Finish = 8; }
|
||||
|
||||
@@ -38,4 +40,14 @@ unsigned int parseHex(const char *_szValue)
|
||||
}
|
||||
}
|
||||
return Value;
|
||||
}
|
||||
|
||||
void DataToHexString(const uint8 *data, size_t size, std::string *output) {
|
||||
Buffer buffer;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
buffer.Printf("%02x ", data[i]);
|
||||
if (i && !(i & 15))
|
||||
buffer.Printf("\n");
|
||||
}
|
||||
buffer.TakeAll(output);
|
||||
}
|
||||
+14
-6
@@ -4,6 +4,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable:4996)
|
||||
#endif
|
||||
@@ -11,18 +13,24 @@
|
||||
// Dumb wrapper around itoa, providing a buffer. Declare this on the stack.
|
||||
class ITOA {
|
||||
public:
|
||||
char buffer[16];
|
||||
const char *p(int i) {
|
||||
sprintf(buffer, "%i", i);
|
||||
return &buffer[0];
|
||||
}
|
||||
char buffer[16];
|
||||
const char *p(int i) {
|
||||
sprintf(buffer, "%i", i);
|
||||
return &buffer[0];
|
||||
}
|
||||
};
|
||||
|
||||
// Other simple string utilities.
|
||||
|
||||
inline bool endsWith(const std::string &str, const std::string &what) {
|
||||
return str.substr(str.size() - what.size()) == what;
|
||||
return str.substr(str.size() - what.size()) == what;
|
||||
}
|
||||
|
||||
void DataToHexString(const uint8 *data, size_t size, std::string *output);
|
||||
inline void StringToHexString(const std::string &data, std::string *output) {
|
||||
DataToHexString((uint8_t *)(&data[0]), data.size(), output);
|
||||
}
|
||||
|
||||
|
||||
// highly unsafe and not recommended.
|
||||
unsigned int parseHex(const char* _szValue);
|
||||
+18
-18
@@ -18,14 +18,14 @@ __int64 _frequency = 0;
|
||||
__int64 _starttime = 0;
|
||||
|
||||
double real_time_now(){
|
||||
if (_frequency == 0) {
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency);
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&_starttime);
|
||||
curtime=0;
|
||||
}
|
||||
__int64 time;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&time);
|
||||
return ((double) (time - _starttime) / (double) _frequency);
|
||||
if (_frequency == 0) {
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency);
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&_starttime);
|
||||
curtime=0;
|
||||
}
|
||||
__int64 time;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&time);
|
||||
return ((double) (time - _starttime) / (double) _frequency);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -47,17 +47,17 @@ void time_update() {
|
||||
curtime = real_time_now();
|
||||
curtime_f = (float)curtime;
|
||||
|
||||
//printf("curtime: %f %f\n", curtime, curtime_f);
|
||||
// also smooth time.
|
||||
//curtime+=float((double) (time-_starttime) / (double) _frequency);
|
||||
//curtime*=0.5f;
|
||||
//curtime+=1.0f/60.0f;
|
||||
//lastTime=curtime;
|
||||
//printf("curtime: %f %f\n", curtime, curtime_f);
|
||||
// also smooth time.
|
||||
//curtime+=float((double) (time-_starttime) / (double) _frequency);
|
||||
//curtime*=0.5f;
|
||||
//curtime+=1.0f/60.0f;
|
||||
//lastTime=curtime;
|
||||
//curtime_f = (float)curtime;
|
||||
}
|
||||
|
||||
float time_now() {
|
||||
return curtime_f;
|
||||
return curtime_f;
|
||||
}
|
||||
|
||||
double time_now_d() {
|
||||
@@ -65,16 +65,16 @@ double time_now_d() {
|
||||
}
|
||||
|
||||
int time_now_ms() {
|
||||
return int(curtime*1000.0);
|
||||
return int(curtime*1000.0);
|
||||
}
|
||||
|
||||
void sleep_ms(int ms) {
|
||||
#ifdef _WIN32
|
||||
#ifndef METRO
|
||||
Sleep(ms);
|
||||
Sleep(ms);
|
||||
#endif
|
||||
#else
|
||||
usleep(ms * 1000);
|
||||
usleep(ms * 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class Listable
|
||||
{
|
||||
public:
|
||||
virtual ~Listable() {}
|
||||
virtual const char *getItem(size_t i) const = 0;
|
||||
virtual size_t numItems() const = 0;
|
||||
|
||||
// Returns -1 for not found.
|
||||
// Child classes are meant to specialize this if they have a faster way
|
||||
// than brute force search.
|
||||
virtual int getIndex(const char *text) {
|
||||
for (size_t i = 0; i < numItems(); i++) {
|
||||
if (!strcmp(getItem(i), text))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
class ArrayListable : public Listable
|
||||
{
|
||||
public:
|
||||
ArrayListable(const char * const*arr, size_t count) : arr_(arr), count_(count) {}
|
||||
virtual ~ArrayListable() {}
|
||||
|
||||
virtual const char *getItem(size_t i) const { return arr_[i]; }
|
||||
virtual size_t numItems() const { return count_; }
|
||||
|
||||
private:
|
||||
const char *const*arr_;
|
||||
size_t count_;
|
||||
};
|
||||
|
||||
class VectorListable : public Listable
|
||||
{
|
||||
VectorListable(const std::vector<std::string> &vec) : vec_(vec) {}
|
||||
virtual ~VectorListable() {}
|
||||
|
||||
virtual const char *getItem(size_t i) const { return vec_[i].c_str(); }
|
||||
virtual size_t numItems() const { return vec_.size(); }
|
||||
|
||||
private:
|
||||
const std::vector<std::string> &vec_;
|
||||
};
|
||||
+6
-1
@@ -50,7 +50,12 @@ const json_value *json_value::get(const char *child_name, json_type type) const
|
||||
}
|
||||
|
||||
const char *json_value::getString(const char *child_name) const {
|
||||
return get(child_name, JSON_STRING)->string_value;
|
||||
const json_value *val = get(child_name, JSON_STRING);
|
||||
if (val)
|
||||
return val->string_value;
|
||||
else
|
||||
FLOG("String %s missing from node %s", child_name, this->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *json_value::getString(const char *child_name, const char *default_value) const {
|
||||
|
||||
@@ -41,6 +41,12 @@ struct json_value
|
||||
int numSiblings() const; // num siblings *after* this one only
|
||||
const json_value *get(const char *child_name) const;
|
||||
const json_value *get(const char *child_name, json_type type) const;
|
||||
const json_value *getArray(const char *child_name) const {
|
||||
return get(child_name, JSON_ARRAY);
|
||||
}
|
||||
const json_value *getDict(const char *child_name) const {
|
||||
return get(child_name, JSON_OBJECT);
|
||||
}
|
||||
const char *getString(const char *child_name) const;
|
||||
const char *getString(const char *child_name, const char *default_value) const;
|
||||
bool getStringVector(std::vector<std::string> *vec) const;
|
||||
@@ -50,6 +56,10 @@ struct json_value
|
||||
int getInt(const char *child_name, int default_value) const;
|
||||
bool getBool(const char *child_name) const;
|
||||
bool getBool(const char *child_name, bool default_value) const;
|
||||
|
||||
bool hasChild(const char *child_name, json_type child_type) const {
|
||||
return get(child_name, child_type) != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(json_value);
|
||||
@@ -101,3 +111,10 @@ private:
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JsonReader);
|
||||
};
|
||||
|
||||
// TODO: Make this a push/pop interface similar to JsonWriter. Maybe
|
||||
// we can get to the point where reading and writing is near identical or the same code.
|
||||
class JsonCursor {
|
||||
public:
|
||||
|
||||
};
|
||||
+174
-174
@@ -5,270 +5,270 @@
|
||||
//#define CHUNKDEBUG
|
||||
|
||||
ChunkFile::ChunkFile(const char *filename, bool _read) {
|
||||
data=0;
|
||||
data=0;
|
||||
fn = filename;
|
||||
fastMode=false;
|
||||
numLevels=0;
|
||||
read=_read;
|
||||
pos=0;
|
||||
didFail=false;
|
||||
fastMode=false;
|
||||
numLevels=0;
|
||||
read=_read;
|
||||
pos=0;
|
||||
didFail=false;
|
||||
|
||||
fastMode = read ? true : false;
|
||||
|
||||
if (fastMode) {
|
||||
if (fastMode) {
|
||||
size_t size;
|
||||
data = (uint8 *)VFSReadFile(filename, &size);
|
||||
if (!data) {
|
||||
ELOG("Chunkfile fail: %s", filename);
|
||||
didFail = true;
|
||||
data = (uint8 *)VFSReadFile(filename, &size);
|
||||
if (!data) {
|
||||
ELOG("Chunkfile fail: %s", filename);
|
||||
didFail = true;
|
||||
return;
|
||||
}
|
||||
eof = size;
|
||||
return;
|
||||
}
|
||||
|
||||
if (file.open(filename, FILE_WRITE)) {
|
||||
didFail=false;
|
||||
eof=file.fileSize();
|
||||
} else {
|
||||
didFail=true;
|
||||
return;
|
||||
}
|
||||
if (file.open(filename, FILE_WRITE)) {
|
||||
didFail=false;
|
||||
eof=file.fileSize();
|
||||
} else {
|
||||
didFail=true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ChunkFile::~ChunkFile() {
|
||||
if (fastMode && data)
|
||||
delete [] data;
|
||||
else
|
||||
file.close();
|
||||
if (fastMode && data)
|
||||
delete [] data;
|
||||
else
|
||||
file.close();
|
||||
}
|
||||
|
||||
int ChunkFile::readInt() {
|
||||
if (pos<eof) {
|
||||
/*
|
||||
int temp = *(int *)(data+pos);
|
||||
pos+=4;
|
||||
*/
|
||||
pos+=4;
|
||||
if (fastMode)
|
||||
return *(int *)(data+pos-4);
|
||||
else
|
||||
return file.readInt();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (pos<eof) {
|
||||
/*
|
||||
int temp = *(int *)(data+pos);
|
||||
pos+=4;
|
||||
*/
|
||||
pos+=4;
|
||||
if (fastMode)
|
||||
return *(int *)(data+pos-4);
|
||||
else
|
||||
return file.readInt();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ChunkFile::writeInt(int i) {
|
||||
/*
|
||||
*(int *)(data+pos) = i;
|
||||
pos+=4;
|
||||
*/
|
||||
/*
|
||||
*(int *)(data+pos) = i;
|
||||
pos+=4;
|
||||
*/
|
||||
#ifndef DEMO_VERSION //if this is missing.. heheh
|
||||
file.writeInt(i);
|
||||
pos+=4;
|
||||
file.writeInt(i);
|
||||
pos+=4;
|
||||
#endif
|
||||
}
|
||||
|
||||
//let's get into the business
|
||||
bool ChunkFile::descend(uint32 id) {
|
||||
id=flipID(id);
|
||||
if (read) {
|
||||
bool found = false;
|
||||
id=flipID(id);
|
||||
if (read) {
|
||||
bool found = false;
|
||||
|
||||
//save information to restore after the next Ascend
|
||||
stack[numLevels].parentStartLocation = pos;
|
||||
stack[numLevels].parentEOF = eof;
|
||||
//save information to restore after the next Ascend
|
||||
stack[numLevels].parentStartLocation = pos;
|
||||
stack[numLevels].parentEOF = eof;
|
||||
|
||||
ChunkInfo temp = stack[numLevels];
|
||||
ChunkInfo temp = stack[numLevels];
|
||||
|
||||
int firstID = 0;
|
||||
//let's search through children..
|
||||
while(pos<eof) {
|
||||
stack[numLevels].ID = readInt();
|
||||
if (firstID == 0) firstID=stack[numLevels].ID|1;
|
||||
stack[numLevels].length = readInt();
|
||||
stack[numLevels].startLocation = pos;
|
||||
int firstID = 0;
|
||||
//let's search through children..
|
||||
while(pos<eof) {
|
||||
stack[numLevels].ID = readInt();
|
||||
if (firstID == 0) firstID=stack[numLevels].ID|1;
|
||||
stack[numLevels].length = readInt();
|
||||
stack[numLevels].startLocation = pos;
|
||||
|
||||
if (stack[numLevels].ID == id)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
} else {
|
||||
seekTo(pos + stack[numLevels].length); //try next block
|
||||
}
|
||||
}
|
||||
if (stack[numLevels].ID == id)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
} else {
|
||||
seekTo(pos + stack[numLevels].length); //try next block
|
||||
}
|
||||
}
|
||||
|
||||
//if we found nothing, return false so the caller can skip this
|
||||
if (!found) {
|
||||
//if we found nothing, return false so the caller can skip this
|
||||
if (!found) {
|
||||
#ifdef CHUNKDEBUG
|
||||
ILOG("Couldn't find %c%c%c%c", id, id>>8, id>>16, id>>24);
|
||||
#endif
|
||||
stack[numLevels]=temp;
|
||||
seekTo(stack[numLevels].parentStartLocation);
|
||||
return false;
|
||||
}
|
||||
stack[numLevels]=temp;
|
||||
seekTo(stack[numLevels].parentStartLocation);
|
||||
return false;
|
||||
}
|
||||
|
||||
//descend into it
|
||||
//pos was set inside the loop above
|
||||
eof = stack[numLevels].startLocation + stack[numLevels].length;
|
||||
numLevels++;
|
||||
//descend into it
|
||||
//pos was set inside the loop above
|
||||
eof = stack[numLevels].startLocation + stack[numLevels].length;
|
||||
numLevels++;
|
||||
#ifdef CHUNKDEBUG
|
||||
ILOG("Descended into %c%c%c%c", id, id>>8, id>>16, id>>24);
|
||||
#endif
|
||||
return true;
|
||||
} else {
|
||||
return true;
|
||||
} else {
|
||||
#ifndef DEMO_VERSION //if this is missing.. heheh
|
||||
//write a chunk id, and prepare for filling in length later
|
||||
writeInt(id);
|
||||
writeInt(0); //will be filled in by Ascend
|
||||
stack[numLevels].startLocation=pos;
|
||||
numLevels++;
|
||||
return true;
|
||||
//write a chunk id, and prepare for filling in length later
|
||||
writeInt(id);
|
||||
writeInt(0); //will be filled in by Ascend
|
||||
stack[numLevels].startLocation=pos;
|
||||
numLevels++;
|
||||
return true;
|
||||
#else
|
||||
return true;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChunkFile::seekTo(int _pos) {
|
||||
if (!fastMode)
|
||||
file.seekBeg(_pos);
|
||||
pos=_pos;
|
||||
if (!fastMode)
|
||||
file.seekBeg(_pos);
|
||||
pos=_pos;
|
||||
}
|
||||
|
||||
//let's ascend out
|
||||
void ChunkFile::ascend() {
|
||||
if (read) {
|
||||
//ascend, and restore information
|
||||
numLevels--;
|
||||
seekTo(stack[numLevels].parentStartLocation);
|
||||
eof = stack[numLevels].parentEOF;
|
||||
if (read) {
|
||||
//ascend, and restore information
|
||||
numLevels--;
|
||||
seekTo(stack[numLevels].parentStartLocation);
|
||||
eof = stack[numLevels].parentEOF;
|
||||
#ifdef CHUNKDEBUG
|
||||
int id = stack[numLevels].ID;
|
||||
ILOG("Ascended out of %c%c%c%c", id, id>>8, id>>16, id>>24);
|
||||
#endif
|
||||
} else {
|
||||
numLevels--;
|
||||
//now fill in the written length automatically
|
||||
int posNow = pos;
|
||||
seekTo(stack[numLevels].startLocation - 4);
|
||||
writeInt(posNow-stack[numLevels].startLocation);
|
||||
seekTo(posNow);
|
||||
}
|
||||
} else {
|
||||
numLevels--;
|
||||
//now fill in the written length automatically
|
||||
int posNow = pos;
|
||||
seekTo(stack[numLevels].startLocation - 4);
|
||||
writeInt(posNow-stack[numLevels].startLocation);
|
||||
seekTo(posNow);
|
||||
}
|
||||
}
|
||||
|
||||
//read a block
|
||||
void ChunkFile::readData(void *what, int count) {
|
||||
if (fastMode)
|
||||
memcpy(what, data + pos, count);
|
||||
else
|
||||
file.read(what,count);
|
||||
if (fastMode)
|
||||
memcpy(what, data + pos, count);
|
||||
else
|
||||
file.read(what,count);
|
||||
|
||||
pos+=count;
|
||||
char temp[4]; //discarded
|
||||
count &= 3;
|
||||
if (count) {
|
||||
count=4-count;
|
||||
if (!fastMode)
|
||||
file.read(temp,count);
|
||||
pos+=count;
|
||||
}
|
||||
pos+=count;
|
||||
char temp[4]; //discarded
|
||||
count &= 3;
|
||||
if (count) {
|
||||
count=4-count;
|
||||
if (!fastMode)
|
||||
file.read(temp,count);
|
||||
pos+=count;
|
||||
}
|
||||
}
|
||||
|
||||
//write a block
|
||||
void ChunkFile::writeData(const void *what, int count) {
|
||||
file.write(what, count);
|
||||
pos+=count;
|
||||
char temp[5]={0,0,0,0,0};
|
||||
count &= 3;
|
||||
if (count)
|
||||
{
|
||||
count=4-count;
|
||||
file.write(temp,count);
|
||||
pos+=count;
|
||||
}
|
||||
file.write(what, count);
|
||||
pos+=count;
|
||||
char temp[5]={0,0,0,0,0};
|
||||
count &= 3;
|
||||
if (count)
|
||||
{
|
||||
count=4-count;
|
||||
file.write(temp,count);
|
||||
pos+=count;
|
||||
}
|
||||
}
|
||||
|
||||
void ChunkFile::writeWString(String str) {
|
||||
wchar_t *text;
|
||||
int len=str.length();
|
||||
wchar_t *text;
|
||||
int len=str.length();
|
||||
#ifdef UNICODE
|
||||
text = str.getPointer();
|
||||
text = str.getPointer();
|
||||
#else
|
||||
text=new wchar_t[len+1];
|
||||
str.toUnicode(text);
|
||||
text=new wchar_t[len+1];
|
||||
str.toUnicode(text);
|
||||
#endif
|
||||
writeInt(len);
|
||||
writeData((char *)text,len*sizeof(wchar_t));
|
||||
writeInt(len);
|
||||
writeData((char *)text,len*sizeof(wchar_t));
|
||||
#ifndef UNICODE
|
||||
delete [] text;
|
||||
delete [] text;
|
||||
#endif
|
||||
}
|
||||
|
||||
String ChunkFile::readWString() {
|
||||
int len=readInt();
|
||||
wchar_t *text = new wchar_t[len+1];
|
||||
readData((char *)text,len*sizeof(wchar_t));
|
||||
text[len]=0;
|
||||
int len=readInt();
|
||||
wchar_t *text = new wchar_t[len+1];
|
||||
readData((char *)text,len*sizeof(wchar_t));
|
||||
text[len]=0;
|
||||
#ifdef UNICODE
|
||||
String s(text);
|
||||
delete [] text;
|
||||
return s;
|
||||
String s(text);
|
||||
delete [] text;
|
||||
return s;
|
||||
#else
|
||||
String temp;
|
||||
temp.fromUnicode(text);
|
||||
delete [] text;
|
||||
return temp;
|
||||
String temp;
|
||||
temp.fromUnicode(text);
|
||||
delete [] text;
|
||||
return temp;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void toUnicode(const std::string &str, uint16 *t) {
|
||||
for (int i=0; i<(int)str.size(); i++) {
|
||||
*t++ = str[i];
|
||||
}
|
||||
*t++ = '\0';
|
||||
for (int i=0; i<(int)str.size(); i++) {
|
||||
*t++ = str[i];
|
||||
}
|
||||
*t++ = '\0';
|
||||
}
|
||||
|
||||
static std::string fromUnicode(const uint16 *src, int len) {
|
||||
struct Local {
|
||||
static int clamp(int i) {
|
||||
return i>255?' ':i;
|
||||
}
|
||||
};
|
||||
struct Local {
|
||||
static int clamp(int i) {
|
||||
return i>255?' ':i;
|
||||
}
|
||||
};
|
||||
|
||||
std::string str;
|
||||
str.resize(len);
|
||||
std::string str;
|
||||
str.resize(len);
|
||||
|
||||
for (int i=0; i<len; i++) {
|
||||
str[i] = Local::clamp(src[i]);
|
||||
}
|
||||
return str;
|
||||
for (int i=0; i<len; i++) {
|
||||
str[i] = Local::clamp(src[i]);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
void ChunkFile::writeString(const std::string &str) {
|
||||
uint16_t *text;
|
||||
int len = str.size();
|
||||
text=new uint16_t[len+1];
|
||||
toUnicode(str, text);
|
||||
writeInt(len);
|
||||
writeData((char *)text,len*sizeof(uint16_t));
|
||||
delete [] text;
|
||||
uint16_t *text;
|
||||
int len = str.size();
|
||||
text=new uint16_t[len+1];
|
||||
toUnicode(str, text);
|
||||
writeInt(len);
|
||||
writeData((char *)text,len*sizeof(uint16_t));
|
||||
delete [] text;
|
||||
}
|
||||
|
||||
std::string ChunkFile::readString() {
|
||||
int len=readInt();
|
||||
uint16_t *text = new uint16_t[len+1];
|
||||
readData((char *)text,len*sizeof(uint16_t));
|
||||
text[len]=0;
|
||||
std::string temp = fromUnicode(text, len);
|
||||
delete [] text;
|
||||
return temp;
|
||||
int len=readInt();
|
||||
uint16_t *text = new uint16_t[len+1];
|
||||
readData((char *)text,len*sizeof(uint16_t));
|
||||
text[len]=0;
|
||||
std::string temp = fromUnicode(text, len);
|
||||
delete [] text;
|
||||
return temp;
|
||||
}
|
||||
int ChunkFile::getCurrentChunkSize() {
|
||||
if (numLevels)
|
||||
return stack[numLevels-1].length;
|
||||
else
|
||||
return 0;
|
||||
if (numLevels)
|
||||
return stack[numLevels-1].length;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
+33
-33
@@ -15,53 +15,53 @@
|
||||
#include "file/easy_file.h"
|
||||
|
||||
inline uint32 flipID(uint32 id) {
|
||||
return ((id>>24)&0xFF) | ((id>>8)&0xFF00) | ((id<<8)&0xFF0000) | ((id<<24)&0xFF000000);
|
||||
return ((id>>24)&0xFF) | ((id>>8)&0xFF00) | ((id<<8)&0xFF0000) | ((id<<24)&0xFF000000);
|
||||
}
|
||||
|
||||
class ChunkFile {
|
||||
public:
|
||||
ChunkFile(const char *filename, bool _read);
|
||||
~ChunkFile();
|
||||
ChunkFile(const char *filename, bool _read);
|
||||
~ChunkFile();
|
||||
|
||||
bool descend(uint32 id);
|
||||
void ascend();
|
||||
bool descend(uint32 id);
|
||||
void ascend();
|
||||
|
||||
int readInt();
|
||||
void readInt(int &i) {i = readInt();}
|
||||
void readData(void *data, int count);
|
||||
String readWString();
|
||||
int readInt();
|
||||
void readInt(int &i) {i = readInt();}
|
||||
void readData(void *data, int count);
|
||||
String readWString();
|
||||
|
||||
void writeString(const std::string &str);
|
||||
std::string readString();
|
||||
|
||||
void writeInt(int i);
|
||||
void writeWString(String str);
|
||||
void writeData(const void *data, int count);
|
||||
void writeInt(int i);
|
||||
void writeWString(String str);
|
||||
void writeData(const void *data, int count);
|
||||
|
||||
int getCurrentChunkSize();
|
||||
bool failed() const {return didFail;}
|
||||
int getCurrentChunkSize();
|
||||
bool failed() const {return didFail;}
|
||||
std::string filename() const { return fn; }
|
||||
|
||||
private:
|
||||
std::string fn;
|
||||
LAMEFile file;
|
||||
struct ChunkInfo {
|
||||
int startLocation;
|
||||
int parentStartLocation;
|
||||
int parentEOF;
|
||||
unsigned int ID;
|
||||
int length;
|
||||
};
|
||||
ChunkInfo stack[8];
|
||||
int numLevels;
|
||||
|
||||
uint8 *data;
|
||||
int pos,eof;
|
||||
bool fastMode;
|
||||
bool read;
|
||||
bool didFail;
|
||||
|
||||
void seekTo(int _pos);
|
||||
int getPos() const {return pos;}
|
||||
LAMEFile file;
|
||||
struct ChunkInfo {
|
||||
int startLocation;
|
||||
int parentStartLocation;
|
||||
int parentEOF;
|
||||
unsigned int ID;
|
||||
int length;
|
||||
};
|
||||
ChunkInfo stack[8];
|
||||
int numLevels;
|
||||
|
||||
uint8 *data;
|
||||
int pos,eof;
|
||||
bool fastMode;
|
||||
bool read;
|
||||
bool didFail;
|
||||
|
||||
void seekTo(int _pos);
|
||||
int getPos() const {return pos;}
|
||||
};
|
||||
|
||||
+43
-43
@@ -10,55 +10,55 @@
|
||||
// An false returned means cancel;
|
||||
bool OpenFileDialog(const char *title, const char *extension, std::string *filename)
|
||||
{
|
||||
OPENFILENAME of;
|
||||
memset(&of, 0, sizeof(of));
|
||||
char buffer[512] = {0};
|
||||
of.lStructSize = sizeof(OPENFILENAME);
|
||||
of.hInstance = 0;
|
||||
of.hwndOwner = GetActiveWindow();
|
||||
OPENFILENAME of;
|
||||
memset(&of, 0, sizeof(of));
|
||||
char buffer[512] = {0};
|
||||
of.lStructSize = sizeof(OPENFILENAME);
|
||||
of.hInstance = 0;
|
||||
of.hwndOwner = GetActiveWindow();
|
||||
|
||||
// These weird strings with zeroes in them can't be dealt with using normal string
|
||||
// functions, so here we go - evil hackery.
|
||||
char filter[256] = "XXX files\0*.XXX\0\0";
|
||||
memcpy(filter, extension, 3);
|
||||
memcpy(filter + 12, extension, 3);
|
||||
of.lpstrFilter = filter;
|
||||
// These weird strings with zeroes in them can't be dealt with using normal string
|
||||
// functions, so here we go - evil hackery.
|
||||
char filter[256] = "XXX files\0*.XXX\0\0";
|
||||
memcpy(filter, extension, 3);
|
||||
memcpy(filter + 12, extension, 3);
|
||||
of.lpstrFilter = filter;
|
||||
|
||||
of.lpstrDefExt = extension;
|
||||
of.lpstrFile = buffer;
|
||||
of.nMaxFile = 511;
|
||||
of.lpstrDefExt = extension;
|
||||
of.lpstrFile = buffer;
|
||||
of.nMaxFile = 511;
|
||||
|
||||
of.Flags = OFN_FILEMUSTEXIST;
|
||||
if (!GetOpenFileName(&of)) return false;
|
||||
*filename = of.lpstrFile;
|
||||
return true;
|
||||
of.Flags = OFN_FILEMUSTEXIST;
|
||||
if (!GetOpenFileName(&of)) return false;
|
||||
*filename = of.lpstrFile;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SaveFileDialog(const char *title, const char *extension, std::string *filename)
|
||||
{
|
||||
OPENFILENAME of;
|
||||
memset(&of, 0, sizeof(of));
|
||||
char buffer[512] = {0};
|
||||
of.lStructSize = sizeof(OPENFILENAME);
|
||||
of.hInstance = 0;
|
||||
of.hwndOwner = GetActiveWindow();
|
||||
OPENFILENAME of;
|
||||
memset(&of, 0, sizeof(of));
|
||||
char buffer[512] = {0};
|
||||
of.lStructSize = sizeof(OPENFILENAME);
|
||||
of.hInstance = 0;
|
||||
of.hwndOwner = GetActiveWindow();
|
||||
|
||||
// These weird strings with zeroes in them can't be dealt with using normal string
|
||||
// functions, so here we go - evil hackery.
|
||||
char filter[256] = "XXX files\0*.XXX\0\0";
|
||||
memcpy(filter, extension, 3);
|
||||
memcpy(filter + 12, extension, 3);
|
||||
of.lpstrFilter = filter;
|
||||
// These weird strings with zeroes in them can't be dealt with using normal string
|
||||
// functions, so here we go - evil hackery.
|
||||
char filter[256] = "XXX files\0*.XXX\0\0";
|
||||
memcpy(filter, extension, 3);
|
||||
memcpy(filter + 12, extension, 3);
|
||||
of.lpstrFilter = filter;
|
||||
|
||||
of.lpstrDefExt = extension;
|
||||
of.lpstrFile = buffer;
|
||||
of.nMaxFile = 511;
|
||||
of.lpstrDefExt = extension;
|
||||
of.lpstrFile = buffer;
|
||||
of.nMaxFile = 511;
|
||||
|
||||
of.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
|
||||
if (!GetSaveFileName(&of))
|
||||
return false;
|
||||
*filename = of.lpstrFile;
|
||||
return true;
|
||||
of.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
|
||||
if (!GetSaveFileName(&of))
|
||||
return false;
|
||||
*filename = of.lpstrFile;
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -69,14 +69,14 @@ bool SaveFileDialog(const char *title, const char *extension, std::string *filen
|
||||
|
||||
bool OpenFileDialog(const char *title, const char *extension, std::string *filename)
|
||||
{
|
||||
ELOG("Asked for OpenFileDialog, not present on this platform.");
|
||||
return false;
|
||||
ELOG("Asked for OpenFileDialog, not present on this platform.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SaveFileDialog(const char *title, const char *extension, std::string *filename)
|
||||
{
|
||||
ELOG("Asked for SaveFileDialog, not present on this platform.");
|
||||
return false;
|
||||
ELOG("Asked for SaveFileDialog, not present on this platform.");
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
+50
-50
@@ -5,87 +5,87 @@
|
||||
#include "file/easy_file.h"
|
||||
|
||||
LAMEFile::LAMEFile() : file_(NULL) {
|
||||
isOpen = false;
|
||||
isOpen = false;
|
||||
}
|
||||
|
||||
LAMEFile::~LAMEFile() { }
|
||||
|
||||
bool LAMEFile::open(const char *filename, eFileMode mode) {
|
||||
file_ = fopen(filename, mode == FILE_READ ? "rb" : "wb");
|
||||
file_ = fopen(filename, mode == FILE_READ ? "rb" : "wb");
|
||||
|
||||
if (!file_) {
|
||||
isOpen = false;
|
||||
} else {
|
||||
isOpen = true;
|
||||
if (mode == FILE_READ) {
|
||||
fseek(file_, 0, SEEK_END);
|
||||
size_ = ftell(file_);
|
||||
fseek(file_, 0, SEEK_SET);
|
||||
}
|
||||
}
|
||||
return isOpen;
|
||||
if (!file_) {
|
||||
isOpen = false;
|
||||
} else {
|
||||
isOpen = true;
|
||||
if (mode == FILE_READ) {
|
||||
fseek(file_, 0, SEEK_END);
|
||||
size_ = ftell(file_);
|
||||
fseek(file_, 0, SEEK_SET);
|
||||
}
|
||||
}
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
void LAMEFile::close() {
|
||||
if (isOpen) {
|
||||
//close the file and reset variables
|
||||
fclose(file_);
|
||||
file_ = NULL;
|
||||
isOpen=false;
|
||||
}
|
||||
if (isOpen) {
|
||||
//close the file and reset variables
|
||||
fclose(file_);
|
||||
file_ = NULL;
|
||||
isOpen=false;
|
||||
}
|
||||
}
|
||||
|
||||
int LAMEFile::fileSize() {
|
||||
if (!isOpen) //of course
|
||||
return 0;
|
||||
else
|
||||
return size_;
|
||||
if (!isOpen) //of course
|
||||
return 0;
|
||||
else
|
||||
return size_;
|
||||
}
|
||||
|
||||
std::string LAMEFile::readAll() {
|
||||
std::string s;
|
||||
size_t size = fileSize();
|
||||
s.resize(size);
|
||||
read(&s[0], size);
|
||||
return s;
|
||||
std::string s;
|
||||
size_t size = fileSize();
|
||||
s.resize(size);
|
||||
read(&s[0], size);
|
||||
return s;
|
||||
}
|
||||
|
||||
int LAMEFile::write(const void *data, int size) {
|
||||
if (isOpen) {
|
||||
return fwrite(data, 1, size, file_); //we return the number of bytes that actually got written
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (isOpen) {
|
||||
return fwrite(data, 1, size, file_); //we return the number of bytes that actually got written
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int LAMEFile::read(void *data, int size) {
|
||||
if (isOpen) {
|
||||
return fread(data, 1, size, file_);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (isOpen) {
|
||||
return fread(data, 1, size, file_);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int LAMEFile::readInt() {
|
||||
int temp;
|
||||
if (read(&temp, sizeof(int)))
|
||||
return temp;
|
||||
else
|
||||
return 0;
|
||||
int temp;
|
||||
if (read(&temp, sizeof(int)))
|
||||
return temp;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LAMEFile::writeInt(int i) {
|
||||
write(&i, sizeof(int));
|
||||
write(&i, sizeof(int));
|
||||
}
|
||||
|
||||
char LAMEFile::readChar() {
|
||||
char temp;
|
||||
if (read(&temp, sizeof(char)))
|
||||
return temp;
|
||||
else
|
||||
return 0;
|
||||
char temp;
|
||||
if (read(&temp, sizeof(char)))
|
||||
return temp;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LAMEFile::writeChar(char i) {
|
||||
write(&i,sizeof(char));
|
||||
write(&i,sizeof(char));
|
||||
}
|
||||
+32
-32
@@ -11,48 +11,48 @@
|
||||
// Raw file paths, does not go through VFS.
|
||||
|
||||
enum eFileMode {
|
||||
FILE_READ=5,
|
||||
FILE_WRITE=6
|
||||
FILE_READ=5,
|
||||
FILE_WRITE=6
|
||||
};
|
||||
|
||||
// TODO: Rename.
|
||||
class LAMEFile {
|
||||
public:
|
||||
LAMEFile();
|
||||
virtual ~LAMEFile();
|
||||
LAMEFile();
|
||||
virtual ~LAMEFile();
|
||||
|
||||
bool open(const char *filename, eFileMode mode);
|
||||
bool open(std::string filename, eFileMode mode) {
|
||||
return open(filename.c_str(), mode);
|
||||
}
|
||||
void close();
|
||||
bool open(const char *filename, eFileMode mode);
|
||||
bool open(std::string filename, eFileMode mode) {
|
||||
return open(filename.c_str(), mode);
|
||||
}
|
||||
void close();
|
||||
|
||||
void writeInt(int i);
|
||||
void writeChar(char i);
|
||||
int write(const void *data, int size);
|
||||
void write(const std::string &str) {
|
||||
write((void *)str.data(), str.size());
|
||||
}
|
||||
void writeInt(int i);
|
||||
void writeChar(char i);
|
||||
int write(const void *data, int size);
|
||||
void write(const std::string &str) {
|
||||
write((void *)str.data(), str.size());
|
||||
}
|
||||
|
||||
int readInt();
|
||||
char readChar();
|
||||
int read(void *data, int size);
|
||||
int readInt();
|
||||
char readChar();
|
||||
int read(void *data, int size);
|
||||
|
||||
std::string readAll();
|
||||
std::string readAll();
|
||||
|
||||
int fileSize();
|
||||
int fileSize();
|
||||
|
||||
void seekBeg(int pos) {
|
||||
if (isOpen) fseek(file_,pos,SEEK_SET);
|
||||
}
|
||||
void seekEnd(int pos) {
|
||||
if (isOpen) fseek(file_,pos,SEEK_END);
|
||||
}
|
||||
void seekCurrent(int pos) {
|
||||
if (isOpen) fseek(file_,pos,SEEK_CUR);
|
||||
}
|
||||
void seekBeg(int pos) {
|
||||
if (isOpen) fseek(file_,pos,SEEK_SET);
|
||||
}
|
||||
void seekEnd(int pos) {
|
||||
if (isOpen) fseek(file_,pos,SEEK_END);
|
||||
}
|
||||
void seekCurrent(int pos) {
|
||||
if (isOpen) fseek(file_,pos,SEEK_CUR);
|
||||
}
|
||||
private:
|
||||
FILE *file_;
|
||||
bool isOpen;
|
||||
int size_;
|
||||
FILE *file_;
|
||||
bool isOpen;
|
||||
int size_;
|
||||
};
|
||||
@@ -0,0 +1,121 @@
|
||||
#include "file/fd_util.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
namespace fd_util {
|
||||
|
||||
// Slow as hell and should only be used for prototyping.
|
||||
// Reads from a socket, up to an '\n'. This means that if the line ends
|
||||
// with '\r', the '\r' will be returned.
|
||||
ssize_t ReadLine(int fd, char *vptr, size_t buf_size) {
|
||||
char *buffer = vptr;
|
||||
size_t n;
|
||||
for (n = 1; n < buf_size; n++) {
|
||||
char c;
|
||||
ssize_t rc;
|
||||
if ((rc = read(fd, &c, 1)) == 1) {
|
||||
*buffer++ = c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
else if (rc == 0) {
|
||||
if (n == 1)
|
||||
return 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
FLOG("Error in Readline()");
|
||||
}
|
||||
}
|
||||
|
||||
*buffer = 0;
|
||||
return n;
|
||||
}
|
||||
|
||||
// Misnamed, it just writes raw data in a retry loop.
|
||||
ssize_t WriteLine(int fd, const char *vptr, size_t n) {
|
||||
const char *buffer = vptr;
|
||||
size_t nleft = n;
|
||||
|
||||
while (nleft > 0) {
|
||||
ssize_t nwritten;
|
||||
if ((nwritten = write(fd, buffer, nleft)) <= 0) {
|
||||
if (errno == EINTR)
|
||||
nwritten = 0;
|
||||
else
|
||||
FLOG("Error in Writeline()");
|
||||
}
|
||||
nleft -= nwritten;
|
||||
buffer += nwritten;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
ssize_t WriteLine(int fd, const char *buffer) {
|
||||
return WriteLine(fd, buffer, strlen(buffer));
|
||||
}
|
||||
|
||||
ssize_t Write(int fd, const std::string &str) {
|
||||
return WriteLine(fd, str.c_str(), str.size());
|
||||
}
|
||||
|
||||
bool WaitUntilReady(int fd, double timeout) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = floor(timeout);
|
||||
tv.tv_usec = (timeout - floor(timeout)) * 1000000.0;
|
||||
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
// First argument to select is the highest socket in the set + 1.
|
||||
int rval = select(fd + 1, &fds, NULL, NULL, &tv);
|
||||
if (rval < 0) {
|
||||
// Error calling select.
|
||||
return false;
|
||||
} else if (rval == 0) {
|
||||
// Timeout.
|
||||
return false;
|
||||
} else {
|
||||
// Socket is ready.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetNonBlocking(int sock, bool non_blocking) {
|
||||
#ifndef _WIN32
|
||||
int opts = fcntl(sock, F_GETFL);
|
||||
if (opts < 0) {
|
||||
perror("fcntl(F_GETFL)");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (non_blocking) {
|
||||
opts = (opts | O_NONBLOCK);
|
||||
} else {
|
||||
opts = (opts & ~O_NONBLOCK);
|
||||
}
|
||||
|
||||
if (fcntl(sock, F_SETFL, opts) < 0) {
|
||||
perror("fcntl(F_SETFL)");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
WLOG("NonBlocking mode not supported on Win32");
|
||||
#endif
|
||||
}
|
||||
|
||||
} // fd_util
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef _FD_UTIL
|
||||
#define _FD_UTIL
|
||||
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
namespace fd_util {
|
||||
|
||||
// Slow as hell and should only be used for prototyping.
|
||||
ssize_t ReadLine(int fd, char *buffer, size_t buf_size);
|
||||
|
||||
// Decently fast.
|
||||
ssize_t WriteLine(int fd, const char *buffer, size_t buf_size);
|
||||
ssize_t WriteLine(int fd, const char *buffer);
|
||||
ssize_t Write(int fd, const std::string &str);
|
||||
|
||||
// Returns true if the fd became ready, false if it didn't or
|
||||
// if there was another error.
|
||||
bool WaitUntilReady(int fd, double timeout);
|
||||
|
||||
void SetNonBlocking(int fd, bool non_blocking);
|
||||
|
||||
} // fd_util
|
||||
|
||||
#endif // _FD_UTIL
|
||||
+79
-79
@@ -14,47 +14,47 @@
|
||||
|
||||
bool writeStringToFile(bool text_file, const std::string &str, const char *filename)
|
||||
{
|
||||
FILE *f = fopen(filename, text_file ? "w" : "wb");
|
||||
if (!f)
|
||||
return false;
|
||||
size_t len = str.size();
|
||||
if (len != fwrite(str.data(), 1, str.size(), f))
|
||||
{
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
fclose(f);
|
||||
return true;
|
||||
FILE *f = fopen(filename, text_file ? "w" : "wb");
|
||||
if (!f)
|
||||
return false;
|
||||
size_t len = str.size();
|
||||
if (len != fwrite(str.data(), 1, str.size(), f))
|
||||
{
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t GetSize(FILE *f)
|
||||
{
|
||||
// can't use off_t here because it can be 32-bit
|
||||
uint64_t pos = ftell(f);
|
||||
if (fseek(f, 0, SEEK_END) != 0) {
|
||||
return 0;
|
||||
}
|
||||
uint64_t size = ftell(f);
|
||||
// can't use off_t here because it can be 32-bit
|
||||
uint64_t pos = ftell(f);
|
||||
if (fseek(f, 0, SEEK_END) != 0) {
|
||||
return 0;
|
||||
}
|
||||
uint64_t size = ftell(f);
|
||||
// Reset the seek position to where it was when we started.
|
||||
if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) {
|
||||
if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) {
|
||||
// Should error here
|
||||
return 0;
|
||||
}
|
||||
return size;
|
||||
return 0;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
bool ReadFileToString(bool text_file, const char *filename, std::string &str)
|
||||
{
|
||||
FILE *f = fopen(filename, text_file ? "r" : "rb");
|
||||
if (!f)
|
||||
return false;
|
||||
size_t len = (size_t)GetSize(f);
|
||||
char *buf = new char[len + 1];
|
||||
buf[fread(buf, 1, len, f)] = 0;
|
||||
str = std::string(buf, len);
|
||||
fclose(f);
|
||||
delete [] buf;
|
||||
return true;
|
||||
FILE *f = fopen(filename, text_file ? "r" : "rb");
|
||||
if (!f)
|
||||
return false;
|
||||
size_t len = (size_t)GetSize(f);
|
||||
char *buf = new char[len + 1];
|
||||
buf[fread(buf, 1, len, f)] = 0;
|
||||
str = std::string(buf, len);
|
||||
fclose(f);
|
||||
delete [] buf;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define DIR_SEP "/"
|
||||
@@ -63,77 +63,77 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str)
|
||||
|
||||
size_t getFilesInDir(const char *directory, std::vector<std::string> *files)
|
||||
{
|
||||
size_t foundEntries = 0;
|
||||
size_t foundEntries = 0;
|
||||
#ifdef _WIN32
|
||||
// Find the first file in the directory.
|
||||
WIN32_FIND_DATA ffd;
|
||||
// Find the first file in the directory.
|
||||
WIN32_FIND_DATA ffd;
|
||||
#ifdef UNICODE
|
||||
HANDLE hFind = FindFirstFile((std::wstring(directory) + "\\*").c_str(), &ffd);
|
||||
HANDLE hFind = FindFirstFile((std::wstring(directory) + "\\*").c_str(), &ffd);
|
||||
#else
|
||||
HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd);
|
||||
HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd);
|
||||
#endif
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FindClose(hFind);
|
||||
return foundEntries;
|
||||
}
|
||||
// windows loop
|
||||
do
|
||||
{
|
||||
const std::string virtualName(ffd.cFileName);
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FindClose(hFind);
|
||||
return foundEntries;
|
||||
}
|
||||
// windows loop
|
||||
do
|
||||
{
|
||||
const std::string virtualName(ffd.cFileName);
|
||||
#else
|
||||
struct dirent dirent, *result = NULL;
|
||||
struct dirent dirent, *result = NULL;
|
||||
|
||||
DIR *dirp = opendir(directory);
|
||||
if (!dirp)
|
||||
return 0;
|
||||
DIR *dirp = opendir(directory);
|
||||
if (!dirp)
|
||||
return 0;
|
||||
|
||||
// non windows loop
|
||||
while (!readdir_r(dirp, &dirent, &result) && result)
|
||||
{
|
||||
const std::string virtualName(result->d_name);
|
||||
// non windows loop
|
||||
while (!readdir_r(dirp, &dirent, &result) && result)
|
||||
{
|
||||
const std::string virtualName(result->d_name);
|
||||
#endif
|
||||
// check for "." and ".."
|
||||
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
|
||||
((virtualName[0] == '.') && (virtualName[1] == '.') &&
|
||||
(virtualName[2] == '\0')))
|
||||
continue;
|
||||
// check for "." and ".."
|
||||
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
|
||||
((virtualName[0] == '.') && (virtualName[1] == '.') &&
|
||||
(virtualName[2] == '\0')))
|
||||
continue;
|
||||
|
||||
files->push_back(std::string(directory) + virtualName);
|
||||
files->push_back(std::string(directory) + virtualName);
|
||||
#ifdef _WIN32
|
||||
} while (FindNextFile(hFind, &ffd) != 0);
|
||||
FindClose(hFind);
|
||||
} while (FindNextFile(hFind, &ffd) != 0);
|
||||
FindClose(hFind);
|
||||
#else
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
#endif
|
||||
return foundEntries;
|
||||
return foundEntries;
|
||||
}
|
||||
|
||||
void deleteFile(const char *file)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!DeleteFile(file)) {
|
||||
ELOG("Error deleting %s: %i", file, GetLastError());
|
||||
}
|
||||
if (!DeleteFile(file)) {
|
||||
ELOG("Error deleting %s: %i", file, GetLastError());
|
||||
}
|
||||
#else
|
||||
int err = unlink(file);
|
||||
if (err) {
|
||||
ELOG("Error unlinking %s: %i", file, err);
|
||||
}
|
||||
int err = unlink(file);
|
||||
if (err) {
|
||||
ELOG("Error unlinking %s: %i", file, err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string getDir(const std::string &path)
|
||||
{
|
||||
int n = path.size() - 1;
|
||||
while (n >= 0 && path[n] != '\\' && path[n] != '/')
|
||||
n--;
|
||||
std::string cutpath = path.substr(0, n);
|
||||
for (size_t i = 0; i < cutpath.size(); i++)
|
||||
{
|
||||
if (cutpath[i] == '\\') cutpath[i] = '/';
|
||||
}
|
||||
return cutpath;
|
||||
int n = path.size() - 1;
|
||||
while (n >= 0 && path[n] != '\\' && path[n] != '/')
|
||||
n--;
|
||||
std::string cutpath = path.substr(0, n);
|
||||
for (size_t i = 0; i < cutpath.size(); i++)
|
||||
{
|
||||
if (cutpath[i] == '\\') cutpath[i] = '/';
|
||||
}
|
||||
return cutpath;
|
||||
}
|
||||
+11
-11
@@ -83,13 +83,13 @@ uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) {
|
||||
#endif
|
||||
|
||||
uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) {
|
||||
char new_path[256] = {0};
|
||||
// Check if it already contains the path
|
||||
char new_path[256] = {0};
|
||||
// Check if it already contains the path
|
||||
if (strlen(path) > strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) {
|
||||
}
|
||||
else {
|
||||
strcpy(new_path, path_);
|
||||
}
|
||||
}
|
||||
else {
|
||||
strcpy(new_path, path_);
|
||||
}
|
||||
strcat(new_path, path);
|
||||
// ILOG("New path: %s", new_path);
|
||||
return ReadLocalFile(new_path, size);
|
||||
@@ -125,11 +125,11 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) {
|
||||
if (0 == memcmp(filename, entries[i].prefix, prefix_len)) {
|
||||
// ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len);
|
||||
uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size);
|
||||
if (data)
|
||||
return data;
|
||||
else
|
||||
continue;
|
||||
// Else try the other registered file systems.
|
||||
if (data)
|
||||
return data;
|
||||
else
|
||||
continue;
|
||||
// Else try the other registered file systems.
|
||||
}
|
||||
}
|
||||
ELOG("Missing filesystem for %s", filename);
|
||||
|
||||
+10
-10
@@ -23,13 +23,13 @@ void glCheckzor(const char *file, int line) {
|
||||
#ifndef ANDROID
|
||||
#if 0
|
||||
void log_callback(GLenum source, GLenum type,
|
||||
GLuint id,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar* message,
|
||||
GLvoid* userParam) {
|
||||
const char *src = "unknown";
|
||||
switch (source) {
|
||||
GLuint id,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar* message,
|
||||
GLvoid* userParam) {
|
||||
const char *src = "unknown";
|
||||
switch (source) {
|
||||
case GL_DEBUG_SOURCE_API_GL_ARB:
|
||||
src = "GL";
|
||||
break;
|
||||
@@ -41,8 +41,8 @@ void log_callback(GLenum source, GLenum type,
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (type) {
|
||||
}
|
||||
switch (type) {
|
||||
case GL_DEBUG_TYPE_ERROR_ARB:
|
||||
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
|
||||
ELOG("%s: %s", src, message);
|
||||
@@ -50,7 +50,7 @@ void log_callback(GLenum source, GLenum type,
|
||||
default:
|
||||
ILOG("%s: %s", src, message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,7 @@ void gl_lost() {
|
||||
return;
|
||||
}
|
||||
for (std::list<GfxResourceHolder *>::iterator iter = holders->begin();
|
||||
iter != holders->end(); ++iter) {
|
||||
iter != holders->end(); ++iter) {
|
||||
(*iter)->GLLost();
|
||||
}
|
||||
}
|
||||
|
||||
+63
-63
@@ -68,34 +68,34 @@ static void SetTextureParameters(int zim_flags) {
|
||||
}
|
||||
|
||||
bool Texture::Load(const char *filename) {
|
||||
// hook for generated textures
|
||||
if (!memcmp(filename, "gen:", 4)) {
|
||||
// TODO
|
||||
// return false;
|
||||
int bpp, w, h;
|
||||
bool clamp;
|
||||
uint8_t *data = generateTexture(filename, bpp, w, h, clamp);
|
||||
if (!data)
|
||||
return false;
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
if (bpp == 1) {
|
||||
// hook for generated textures
|
||||
if (!memcmp(filename, "gen:", 4)) {
|
||||
// TODO
|
||||
// return false;
|
||||
int bpp, w, h;
|
||||
bool clamp;
|
||||
uint8_t *data = generateTexture(filename, bpp, w, h, clamp);
|
||||
if (!data)
|
||||
return false;
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
if (bpp == 1) {
|
||||
|
||||
#ifdef ANDROID
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
|
||||
#endif
|
||||
} else {
|
||||
FLOG("unsupported");
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
delete [] data;
|
||||
return true;
|
||||
}
|
||||
#ifdef ANDROID
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
|
||||
#endif
|
||||
} else {
|
||||
FLOG("unsupported");
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
delete [] data;
|
||||
return true;
|
||||
}
|
||||
|
||||
filename_ = filename;
|
||||
|
||||
@@ -123,27 +123,27 @@ bool Texture::Load(const char *filename) {
|
||||
const char *name = fn;
|
||||
if (zim && 0==memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/");
|
||||
len = strlen(name);
|
||||
#ifndef ANDROID
|
||||
#ifndef ANDROID
|
||||
if (!strcmp("png", &name[len-3]) ||
|
||||
!strcmp("PNG", &name[len-3])) {
|
||||
if (!LoadPNG(fn)) {
|
||||
LoadXOR();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
!strcmp("PNG", &name[len-3])) {
|
||||
if (!LoadPNG(fn)) {
|
||||
LoadXOR();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (!strcmp("zim", &name[len-3])) {
|
||||
if (!LoadZIM(name)) {
|
||||
LoadXOR();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
#endif
|
||||
if (!strcmp("zim", &name[len-3])) {
|
||||
if (!LoadZIM(name)) {
|
||||
LoadXOR();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
LoadXOR();
|
||||
return false;
|
||||
LoadXOR();
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef ANDROID
|
||||
@@ -157,7 +157,7 @@ bool Texture::LoadPNG(const char *filename) {
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
SetTextureParameters(ZIM_GEN_MIPS);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image_data);
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image_data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
GL_CHECK();
|
||||
free(image_data);
|
||||
@@ -166,22 +166,22 @@ bool Texture::LoadPNG(const char *filename) {
|
||||
#endif
|
||||
|
||||
bool Texture::LoadXOR() {
|
||||
width_ = height_ = 256;
|
||||
unsigned char *buf = new unsigned char[width_*height_*4];
|
||||
for (int y = 0; y < 256; y++) {
|
||||
for (int x = 0; x < 256; x++) {
|
||||
buf[(y*width_ + x)*4 + 0] = x^y;
|
||||
buf[(y*width_ + x)*4 + 1] = x^y;
|
||||
buf[(y*width_ + x)*4 + 2] = x^y;
|
||||
buf[(y*width_ + x)*4 + 3] = 0xFF;
|
||||
}
|
||||
}
|
||||
width_ = height_ = 256;
|
||||
unsigned char *buf = new unsigned char[width_*height_*4];
|
||||
for (int y = 0; y < 256; y++) {
|
||||
for (int x = 0; x < 256; x++) {
|
||||
buf[(y*width_ + x)*4 + 0] = x^y;
|
||||
buf[(y*width_ + x)*4 + 1] = x^y;
|
||||
buf[(y*width_ + x)*4 + 2] = x^y;
|
||||
buf[(y*width_ + x)*4 + 3] = 0xFF;
|
||||
}
|
||||
}
|
||||
GL_CHECK();
|
||||
glGenTextures(1, &id_);
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
SetTextureParameters(ZIM_GEN_MIPS);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, buf);
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, buf);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
GL_CHECK();
|
||||
delete [] buf;
|
||||
@@ -198,7 +198,7 @@ uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) {
|
||||
for (int y = 0; y < height; y += 4) {
|
||||
for (int x = 0; x < width; x += 4) {
|
||||
DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8,
|
||||
rgba + (y * width + x) * 4, width, 255);
|
||||
rgba + (y * width + x) * 4, width, 255);
|
||||
}
|
||||
}
|
||||
return rgba;
|
||||
@@ -256,7 +256,7 @@ bool Texture::LoadZIM(const char *filename) {
|
||||
#else
|
||||
image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h);
|
||||
glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]);
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]);
|
||||
#endif
|
||||
}
|
||||
GL_CHECK();
|
||||
@@ -266,7 +266,7 @@ bool Texture::LoadZIM(const char *filename) {
|
||||
} else {
|
||||
for (int l = 0; l < num_levels; l++) {
|
||||
glTexImage2D(GL_TEXTURE_2D, l, storage, width[l], height[l], 0,
|
||||
colors, data_type, image_data[l]);
|
||||
colors, data_type, image_data[l]);
|
||||
}
|
||||
if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) {
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
@@ -282,8 +282,8 @@ bool Texture::LoadZIM(const char *filename) {
|
||||
|
||||
void Texture::Bind(int stage) {
|
||||
GL_CHECK();
|
||||
if (stage != -1)
|
||||
glActiveTexture(GL_TEXTURE0 + stage);
|
||||
if (stage != -1)
|
||||
glActiveTexture(GL_TEXTURE0 + stage);
|
||||
glBindTexture(GL_TEXTURE_2D, id_);
|
||||
GL_CHECK();
|
||||
}
|
||||
+5
-5
@@ -9,7 +9,7 @@
|
||||
#include "gfx/gl_lost_manager.h"
|
||||
|
||||
class Texture : public GfxResourceHolder {
|
||||
public:
|
||||
public:
|
||||
Texture();
|
||||
~Texture();
|
||||
|
||||
@@ -18,10 +18,10 @@ class Texture : public GfxResourceHolder {
|
||||
bool LoadPNG(const char *filename);
|
||||
#endif
|
||||
bool LoadXOR(); // Loads a placeholder texture.
|
||||
|
||||
|
||||
// Deduces format from the filename.
|
||||
// If loading fails, will load a 256x256 XOR texture.
|
||||
// If filename begins with "gen:", will defer to texture_gen.cpp/h.
|
||||
// If filename begins with "gen:", will defer to texture_gen.cpp/h.
|
||||
bool Load(const char *filename);
|
||||
|
||||
void Bind(int stage = -1);
|
||||
@@ -35,10 +35,10 @@ class Texture : public GfxResourceHolder {
|
||||
virtual void GLLost();
|
||||
std::string filename() const { return filename_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
std::string filename_;
|
||||
#ifdef METRO
|
||||
ID3D11Texture2D *tex_;
|
||||
ID3D11Texture2D *tex_;
|
||||
#endif
|
||||
unsigned int id_;
|
||||
int width_, height_;
|
||||
|
||||
+36
-36
@@ -12,42 +12,42 @@
|
||||
|
||||
|
||||
uint8_t *generateTexture(const char *filename, int &bpp, int &w, int &h, bool &clamp) {
|
||||
char name_and_params[256];
|
||||
// security check :)
|
||||
if (strlen(filename) > 200)
|
||||
return 0;
|
||||
sscanf(filename, "gen:%i:%i:%s", &w, &h, name_and_params);
|
||||
char name_and_params[256];
|
||||
// security check :)
|
||||
if (strlen(filename) > 200)
|
||||
return 0;
|
||||
sscanf(filename, "gen:%i:%i:%s", &w, &h, name_and_params);
|
||||
|
||||
bool mip = false;
|
||||
uint8_t *data;
|
||||
if (!strcmp(name_and_params, "vignette")) {
|
||||
bpp = 1;
|
||||
data = new uint8_t[w*h];
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
float dx = (float)(x - w/2) / (w/2);
|
||||
float dy = (float)(y - h/2) / (h/2);
|
||||
float dist = sqrtf(dx * dx + dy * dy);
|
||||
dist /= 1.414f;
|
||||
float val = 1.0 - powf(dist, 1.4f);
|
||||
data[y*w + x] = val * 255;
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(name_and_params, "circle")) {
|
||||
bpp = 1;
|
||||
// TODO
|
||||
data = new uint8_t[w*h];
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
float dx = (float)(x - w/2) / (w/2);
|
||||
float dy = (float)(y - h/2) / (h/2);
|
||||
float dist = sqrtf(dx * dx + dy * dy);
|
||||
dist /= 1.414f;
|
||||
float val = 1.0 - powf(dist, 1.4f);
|
||||
data[y*w + x] = val * 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool mip = false;
|
||||
uint8_t *data;
|
||||
if (!strcmp(name_and_params, "vignette")) {
|
||||
bpp = 1;
|
||||
data = new uint8_t[w*h];
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
float dx = (float)(x - w/2) / (w/2);
|
||||
float dy = (float)(y - h/2) / (h/2);
|
||||
float dist = sqrtf(dx * dx + dy * dy);
|
||||
dist /= 1.414f;
|
||||
float val = 1.0 - powf(dist, 1.4f);
|
||||
data[y*w + x] = val * 255;
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(name_and_params, "circle")) {
|
||||
bpp = 1;
|
||||
// TODO
|
||||
data = new uint8_t[w*h];
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
float dx = (float)(x - w/2) / (w/2);
|
||||
float dy = (float)(y - h/2) / (h/2);
|
||||
float dist = sqrtf(dx * dx + dy * dy);
|
||||
dist /= 1.414f;
|
||||
float val = 1.0 - powf(dist, 1.4f);
|
||||
data[y*w + x] = val * 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
return data;
|
||||
}
|
||||
+148
-117
@@ -10,7 +10,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "base/display.h"
|
||||
#include "base/logging.h"
|
||||
#include "math/math_util.h"
|
||||
#include "gfx_es2/draw_buffer.h"
|
||||
@@ -38,7 +41,7 @@ void DrawBuffer::Begin(DrawBufferMode dbmode) {
|
||||
}
|
||||
|
||||
void DrawBuffer::End() {
|
||||
// Currently does nothing, but call it!
|
||||
// Currently does nothing, but call it!
|
||||
}
|
||||
|
||||
void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) {
|
||||
@@ -46,10 +49,10 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) {
|
||||
return;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
if (set_blend_state) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
if (set_blend_state) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
glUniform1i(program->sampler0, 0);
|
||||
glEnableVertexAttribArray(program->a_position);
|
||||
glEnableVertexAttribArray(program->a_color);
|
||||
@@ -57,7 +60,7 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) {
|
||||
glEnableVertexAttribArray(program->a_texcoord0);
|
||||
GL_CHECK();
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].x);
|
||||
glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &verts_[0].r);
|
||||
glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &verts_[0].rgba);
|
||||
if (program->a_texcoord0 != -1)
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].u);
|
||||
glDrawArrays(mode_ == DBMODE_LINES ? GL_LINES : GL_TRIANGLES, 0, count_);
|
||||
@@ -68,54 +71,50 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) {
|
||||
glDisableVertexAttribArray(program->a_texcoord0);
|
||||
GL_CHECK();
|
||||
|
||||
count_ = 0;
|
||||
count_ = 0;
|
||||
}
|
||||
|
||||
void DrawBuffer::V(float x, float y, float z, uint32 color, float u, float v) {
|
||||
Vertex *vert = &verts_[count_++];
|
||||
Vertex *vert = &verts_[count_++];
|
||||
vert->x = x;
|
||||
vert->y = y;
|
||||
vert->z = z;
|
||||
// todo: speedup rgba here
|
||||
vert->r = color & 0xFF;
|
||||
vert->g = (color >> 8) & 0xFF;
|
||||
vert->b = (color >> 16) & 0xFF;
|
||||
vert->a = (color >> 24) & 0xFF;
|
||||
vert->rgba = color;
|
||||
vert->u = u;
|
||||
vert->v = v;
|
||||
}
|
||||
|
||||
void DrawBuffer::Rect(float x, float y, float w, float h, uint32 color, int align) {
|
||||
DoAlign(align, &x, &y, w, h);
|
||||
DoAlign(align, &x, &y, &w, &h);
|
||||
RectVGradient(x, y, w, h, color, color);
|
||||
}
|
||||
|
||||
void DrawBuffer::RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom) {
|
||||
V(x, y, 0, colorTop, 0, 0);
|
||||
V(x + w, y, 0, colorTop, 1, 0);
|
||||
V(x + w, y + h, 0, colorBottom, 1, 1);
|
||||
V(x, y, 0, colorTop, 0, 0);
|
||||
V(x + w, y + h, 0, colorBottom, 1, 1);
|
||||
V(x, y + h, 0, colorBottom, 0, 1);
|
||||
V(x, y, 0, colorTop, 0, 0);
|
||||
V(x + w, y, 0, colorTop, 1, 0);
|
||||
V(x + w, y + h, 0, colorBottom, 1, 1);
|
||||
V(x, y, 0, colorTop, 0, 0);
|
||||
V(x + w, y + h, 0, colorBottom, 1, 1);
|
||||
V(x, y + h, 0, colorBottom, 0, 1);
|
||||
}
|
||||
|
||||
void DrawBuffer::MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops) {
|
||||
for (int i = 0; i < numStops - 1; i++) {
|
||||
float t0 = stops[i].t, t1 = stops[i+1].t;
|
||||
uint32_t c0 = stops[i].t, c1 = stops[i+1].t;
|
||||
RectVGradient(x, y + h * t0, w, h * (t1 - t0), c0, c1);
|
||||
}
|
||||
for (int i = 0; i < numStops - 1; i++) {
|
||||
float t0 = stops[i].t, t1 = stops[i+1].t;
|
||||
uint32_t c0 = stops[i].t, c1 = stops[i+1].t;
|
||||
RectVGradient(x, y + h * t0, w, h * (t1 - t0), c0, c1);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawBuffer::Rect(float x, float y, float w, float h,
|
||||
float u, float v, float uw, float uh,
|
||||
uint32 color) {
|
||||
V(x, y, 0, color, u, v);
|
||||
V(x + w, y, 0, color, u + uw, v);
|
||||
V(x + w, y + h, 0, color, u + uw, v + uh);
|
||||
V(x, y, 0, color, u, v);
|
||||
V(x + w, y + h, 0, color, u + uw, v + uh);
|
||||
V(x, y + h, 0, color, u, v + uh);
|
||||
float u, float v, float uw, float uh,
|
||||
uint32 color) {
|
||||
V(x, y, 0, color, u, v);
|
||||
V(x + w, y, 0, color, u + uw, v);
|
||||
V(x + w, y + h, 0, color, u + uw, v + uh);
|
||||
V(x, y, 0, color, u, v);
|
||||
V(x + w, y + h, 0, color, u + uw, v + uh);
|
||||
V(x, y + h, 0, color, u, v + uh);
|
||||
}
|
||||
|
||||
void DrawBuffer::MeasureImage(int atlas_image, float *w, float *h) {
|
||||
@@ -128,10 +127,10 @@ void DrawBuffer::DrawImage(int atlas_image, float x, float y, float scale, Color
|
||||
const AtlasImage &image = atlas->images[atlas_image];
|
||||
float w = (float)image.w * scale;
|
||||
float h = (float)image.h * scale;
|
||||
if (align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (align & ALIGN_RIGHT) x -= w;
|
||||
if (align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (align & ALIGN_BOTTOM) y -= h;
|
||||
if (align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (align & ALIGN_RIGHT) x -= w;
|
||||
if (align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (align & ALIGN_BOTTOM) y -= h;
|
||||
DrawImageStretch(atlas_image, x, y, x + w, y + h, color);
|
||||
}
|
||||
|
||||
@@ -145,76 +144,74 @@ void DrawBuffer::DrawImageStretch(int atlas_image, float x1, float y1, float x2,
|
||||
V(x1, y2, color, image.u1, image.v2);
|
||||
}
|
||||
|
||||
inline void rot(float *v, float angle, float xc, float yc) {
|
||||
v[0]-=xc;
|
||||
v[1]-=yc;
|
||||
|
||||
inline void rot(float *v, float angle, float xc,float yc)
|
||||
{
|
||||
v[0]-=xc;
|
||||
v[1]-=yc;
|
||||
float ca=cosf(angle),sa=sinf(angle);
|
||||
|
||||
float ca=cosf(angle),sa=sinf(angle);
|
||||
float t0 = v[0] * ca + v[1] * -sa;
|
||||
float t1 = v[0] * sa + v[1] * ca;
|
||||
|
||||
float t0 = v[0] * ca + v[1] * -sa;
|
||||
float t1 = v[0] * sa + v[1] * ca;
|
||||
|
||||
v[0] = t0 + xc;
|
||||
v[1] = t1 + yc;
|
||||
v[0] = t0 + xc;
|
||||
v[1] = t1 + yc;
|
||||
}
|
||||
|
||||
|
||||
void DrawBuffer::DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color) {
|
||||
const AtlasImage &image = atlas->images[atlas_image];
|
||||
float w = (float)image.w * scale;
|
||||
float h = (float)image.h * scale;
|
||||
float x1 = x - w / 2;
|
||||
float x2 = x + w / 2;
|
||||
float y1 = y - h / 2;
|
||||
float y2 = y + h / 2;
|
||||
float v[6][2] = {
|
||||
{x1, y1},
|
||||
{x2, y1},
|
||||
{x2, y2},
|
||||
{x1, y1},
|
||||
{x2, y2},
|
||||
{x1, y2},
|
||||
};
|
||||
const float uv[6][2] = {
|
||||
{image.u1, image.v1},
|
||||
{image.u2, image.v1},
|
||||
{image.u2, image.v2},
|
||||
{image.u1, image.v1},
|
||||
{image.u2, image.v2},
|
||||
{image.u1, image.v2},
|
||||
};
|
||||
for (int i = 0; i < 6; i++) {
|
||||
rot(v[i], angle, x, y);
|
||||
V(v[i][0], v[i][1], 0, color, uv[i][0], uv[i][1]);
|
||||
}
|
||||
const AtlasImage &image = atlas->images[atlas_image];
|
||||
float w = (float)image.w * scale;
|
||||
float h = (float)image.h * scale;
|
||||
float x1 = x - w / 2;
|
||||
float x2 = x + w / 2;
|
||||
float y1 = y - h / 2;
|
||||
float y2 = y + h / 2;
|
||||
float v[6][2] = {
|
||||
{x1, y1},
|
||||
{x2, y1},
|
||||
{x2, y2},
|
||||
{x1, y1},
|
||||
{x2, y2},
|
||||
{x1, y2},
|
||||
};
|
||||
const float uv[6][2] = {
|
||||
{image.u1, image.v1},
|
||||
{image.u2, image.v1},
|
||||
{image.u2, image.v2},
|
||||
{image.u1, image.v1},
|
||||
{image.u2, image.v2},
|
||||
{image.u1, image.v2},
|
||||
};
|
||||
for (int i = 0; i < 6; i++) {
|
||||
rot(v[i], angle, x, y);
|
||||
V(v[i][0], v[i][1], 0, color, uv[i][0], uv[i][1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: add arc support
|
||||
void DrawBuffer::Circle(float xc, float yc, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul) {
|
||||
float angleDelta = PI * 2 / segments;
|
||||
float uDelta = 1.0f / segments;
|
||||
float t2 = thickness / 2.0f;
|
||||
float r1 = radius + t2;
|
||||
float r2 = radius - t2;
|
||||
for (int i = 0; i < segments + 1; i++) {
|
||||
float angle1 = i * angleDelta;
|
||||
float angle2 = (i + 1) * angleDelta;
|
||||
float u1 = u_mul * i * uDelta;
|
||||
float u2 = u_mul * (i + 1) * uDelta;
|
||||
// TODO: get rid of one pair of cos/sin per loop, can reuse from last iteration
|
||||
float c1 = cosf(angle1), s1 = sinf(angle1), c2 = cosf(angle2), s2 = sinf(angle2);
|
||||
const float x[4] = {c1 * r1 + xc, c2 * r1 + xc, c1 * r2 + xc, c2 * r2 + xc};
|
||||
const float y[4] = {s1 * r1 + yc, s2 * r1 + yc, s1 * r2 + yc, s2 * r2 + yc};
|
||||
V(x[0], y[0], color, u1, 0);
|
||||
V(x[1], y[1], color, u2, 0);
|
||||
V(x[2], y[2], color, u1, 1);
|
||||
V(x[1], y[1], color, u2, 0);
|
||||
V(x[3], y[3], color, u2, 1);
|
||||
V(x[2], y[2], color, u1, 1);
|
||||
}
|
||||
float angleDelta = PI * 2 / segments;
|
||||
float uDelta = 1.0f / segments;
|
||||
float t2 = thickness / 2.0f;
|
||||
float r1 = radius + t2;
|
||||
float r2 = radius - t2;
|
||||
for (int i = 0; i < segments + 1; i++) {
|
||||
float angle1 = i * angleDelta;
|
||||
float angle2 = (i + 1) * angleDelta;
|
||||
float u1 = u_mul * i * uDelta;
|
||||
float u2 = u_mul * (i + 1) * uDelta;
|
||||
// TODO: get rid of one pair of cos/sin per loop, can reuse from last iteration
|
||||
float c1 = cosf(angle1), s1 = sinf(angle1), c2 = cosf(angle2), s2 = sinf(angle2);
|
||||
const float x[4] = {c1 * r1 + xc, c2 * r1 + xc, c1 * r2 + xc, c2 * r2 + xc};
|
||||
const float y[4] = {s1 * r1 + yc, s2 * r1 + yc, s1 * r2 + yc, s2 * r2 + yc};
|
||||
V(x[0], y[0], color, u1, 0);
|
||||
V(x[1], y[1], color, u2, 0);
|
||||
V(x[2], y[2], color, u1, 1);
|
||||
V(x[1], y[1], color, u2, 0);
|
||||
V(x[3], y[3], color, u2, 1);
|
||||
V(x[2], y[2], color, u1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawBuffer::DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color) {
|
||||
@@ -269,14 +266,14 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) {
|
||||
const AtlasFont &atlasfont = *atlas->fonts[font];
|
||||
unsigned char cval;
|
||||
float wacc = 0, maxh = 0;
|
||||
int lines = 1;
|
||||
int lines = 1;
|
||||
while ((cval = *text++) != '\0') {
|
||||
if (cval < 32) continue;
|
||||
if (cval > 127) continue;
|
||||
if (cval == '\n') {
|
||||
wacc = 0;
|
||||
lines++;
|
||||
}
|
||||
if (cval == '\n') {
|
||||
wacc = 0;
|
||||
lines++;
|
||||
}
|
||||
AtlasChar c = atlasfont.chars[cval - 32];
|
||||
wacc += c.wx * fontscalex;
|
||||
}
|
||||
@@ -285,27 +282,38 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) {
|
||||
}
|
||||
|
||||
void DrawBuffer::DrawTextShadow(int font, const char *text, float x, float y, Color color, int flags) {
|
||||
uint32_t alpha = (color >> 1) & 0xFF000000;
|
||||
uint32_t alpha = (color >> 1) & 0xFF000000;
|
||||
DrawText(font, text, x + 2, y + 2, alpha, flags);
|
||||
DrawText(font, text, x, y, color, flags);
|
||||
}
|
||||
|
||||
void DrawBuffer::DoAlign(int align, float *x, float *y, float w, float h) {
|
||||
if (align & ALIGN_HCENTER) *x -= w / 2;
|
||||
if (align & ALIGN_RIGHT) *x -= w;
|
||||
if (align & ALIGN_VCENTER) *y -= h / 2;
|
||||
if (align & ALIGN_BOTTOM) *y -= h;
|
||||
void DrawBuffer::DoAlign(int flags, float *x, float *y, float *w, float *h) {
|
||||
if (flags & ALIGN_HCENTER) *x -= *w / 2;
|
||||
if (flags & ALIGN_RIGHT) *x -= *w;
|
||||
if (flags & ALIGN_VCENTER) *y -= *h / 2;
|
||||
if (flags & ALIGN_BOTTOM) *y -= *h;
|
||||
if (flags & (ROTATE_90DEG_LEFT | ROTATE_90DEG_RIGHT)) {
|
||||
std::swap(*w, *h);
|
||||
std::swap(*x, *y);
|
||||
}
|
||||
}
|
||||
|
||||
// ROTATE_* doesn't yet work right.
|
||||
void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color color, int flags) {
|
||||
const AtlasFont &atlasfont = *atlas->fonts[font];
|
||||
unsigned char cval;
|
||||
float w, h;
|
||||
MeasureText(font, text, &w, &h);
|
||||
if (flags) {
|
||||
DoAlign(flags, &x, &y, w, h);
|
||||
DoAlign(flags, &x, &y, &w, &h);
|
||||
}
|
||||
y+=atlasfont.ascend*fontscaley;
|
||||
|
||||
if (flags & ROTATE_90DEG_LEFT) {
|
||||
x -= atlasfont.ascend*fontscaley;
|
||||
// y += h;
|
||||
}
|
||||
else
|
||||
y += atlasfont.ascend*fontscaley;
|
||||
float sx = x;
|
||||
while ((cval = *text++) != '\0') {
|
||||
if (cval == '\n') {
|
||||
@@ -316,23 +324,46 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co
|
||||
if (cval < 32) continue;
|
||||
if (cval > 127) continue;
|
||||
AtlasChar c = atlasfont.chars[cval - 32];
|
||||
float cx1 = x + c.ox * fontscalex;
|
||||
float cy1 = y + c.oy * fontscaley;
|
||||
float cx2 = x + (c.ox + c.pw) * fontscalex;
|
||||
float cy2 = y + (c.oy + c.ph) * fontscaley;
|
||||
float cx1, cy1, cx2, cy2;
|
||||
if (flags & ROTATE_90DEG_LEFT) {
|
||||
cy1 = y - c.ox * fontscalex;
|
||||
cx1 = x + c.oy * fontscaley;
|
||||
cy2 = y - (c.ox + c.pw) * fontscalex;
|
||||
cx2 = x + (c.oy + c.ph) * fontscaley;
|
||||
} else {
|
||||
cx1 = x + c.ox * fontscalex;
|
||||
cy1 = y + c.oy * fontscaley;
|
||||
cx2 = x + (c.ox + c.pw) * fontscalex;
|
||||
cy2 = y + (c.oy + c.ph) * fontscaley;
|
||||
}
|
||||
V(cx1, cy1, color, c.sx, c.sy);
|
||||
V(cx2, cy1, color, c.ex, c.sy);
|
||||
V(cx2, cy2, color, c.ex, c.ey);
|
||||
V(cx1, cy1, color, c.sx, c.sy);
|
||||
V(cx2, cy2, color, c.ex, c.ey);
|
||||
V(cx1, cy2, color, c.sx, c.ey);
|
||||
x += c.wx * fontscalex;
|
||||
if (flags & ROTATE_90DEG_LEFT)
|
||||
y -= c.wx * fontscalex;
|
||||
else
|
||||
x += c.wx * fontscalex;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawBuffer::EnableBlend(bool enable) {
|
||||
if (enable)
|
||||
glEnable(GL_BLEND);
|
||||
else
|
||||
glDisable(GL_BLEND);
|
||||
if (enable)
|
||||
glEnable(GL_BLEND);
|
||||
else
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void DrawBuffer::SetClipRect(float x, float y, float w, float h)
|
||||
{
|
||||
// Sigh, OpenGL is upside down.
|
||||
glScissor(x, g_yres - y, w, h);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
void DrawBuffer::NoClip()
|
||||
{
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
+33
-21
@@ -9,17 +9,22 @@ struct Atlas;
|
||||
|
||||
enum {
|
||||
ALIGN_LEFT = 0,
|
||||
ALIGN_RIGHT = 16,
|
||||
ALIGN_TOP = 0,
|
||||
ALIGN_BOTTOM = 1,
|
||||
ALIGN_RIGHT = 16,
|
||||
ALIGN_TOP = 0,
|
||||
ALIGN_BOTTOM = 1,
|
||||
ALIGN_HCENTER = 4,
|
||||
ALIGN_VCENTER = 8,
|
||||
ALIGN_VBASELINE = 32, // text only, possibly not yet working
|
||||
ALIGN_VBASELINE = 32, // text only, possibly not yet working
|
||||
|
||||
ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT,
|
||||
ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT,
|
||||
ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT,
|
||||
ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT,
|
||||
ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT,
|
||||
ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT,
|
||||
ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT,
|
||||
ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT,
|
||||
|
||||
// Only for text drawing
|
||||
ROTATE_90DEG_LEFT = 256,
|
||||
ROTATE_90DEG_RIGHT = 512,
|
||||
ROTATE_180DEG = 1024,
|
||||
};
|
||||
|
||||
struct GLSLProgram;
|
||||
@@ -31,12 +36,12 @@ enum DrawBufferMode {
|
||||
|
||||
struct GradientStop
|
||||
{
|
||||
float t;
|
||||
uint32_t color;
|
||||
float t;
|
||||
uint32_t color;
|
||||
};
|
||||
|
||||
class DrawBuffer {
|
||||
public:
|
||||
public:
|
||||
DrawBuffer();
|
||||
~DrawBuffer();
|
||||
|
||||
@@ -47,21 +52,21 @@ class DrawBuffer {
|
||||
|
||||
void Flush(const GLSLProgram *program, bool set_blend_state=true);
|
||||
void Rect(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT);
|
||||
void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom);
|
||||
void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom);
|
||||
|
||||
void MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops);
|
||||
void MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops);
|
||||
|
||||
void RectCenter(float x, float y, float w, float h, uint32 color) {
|
||||
Rect(x - w/2, y - h/2, w, h, color);
|
||||
}
|
||||
void Rect(float x, float y, float w, float h,
|
||||
float u, float v, float uw, float uh, uint32 color);
|
||||
float u, float v, float uw, float uh, uint32 color);
|
||||
void V(float x, float y, float z, uint32 color, float u, float v);
|
||||
void V(float x, float y, uint32 color, float u, float v) {
|
||||
V(x, y, 0.0f, color, u, v);
|
||||
}
|
||||
|
||||
void Circle(float x, float y, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul);
|
||||
void Circle(float x, float y, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul);
|
||||
|
||||
// New drawing APIs
|
||||
|
||||
@@ -72,7 +77,7 @@ class DrawBuffer {
|
||||
void MeasureImage(int atlas_image, float *w, float *h);
|
||||
void DrawImage(int atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT);
|
||||
void DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF));
|
||||
void DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF)); // Always centers
|
||||
void DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF)); // Always centers
|
||||
void DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color);
|
||||
// Results in 18 triangles. Kind of expensive for a button.
|
||||
void DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF), float corner_scale = 1.0);
|
||||
@@ -89,14 +94,21 @@ class DrawBuffer {
|
||||
fontscaley = ys;
|
||||
}
|
||||
|
||||
// Utility to avoid having to include gl.h just for this in UI code.
|
||||
void EnableBlend(bool enable);
|
||||
// Utility to avoid having to include gl.h just for this in UI code.
|
||||
void EnableBlend(bool enable);
|
||||
|
||||
private:
|
||||
void DoAlign(int align, float *x, float *y, float w, float h);
|
||||
|
||||
// Rectangular clipping, implemented using scissoring.
|
||||
// Must flush before and after.
|
||||
void SetClipRect(float x1, float y1, float x2, float y2);
|
||||
void NoClip();
|
||||
|
||||
|
||||
private:
|
||||
void DoAlign(int flags, float *x, float *y, float *w, float *h);
|
||||
struct Vertex {
|
||||
float x, y, z;
|
||||
uint8 r, g, b, a;
|
||||
uint32_t rgba;
|
||||
float u, v;
|
||||
};
|
||||
|
||||
|
||||
+9
-9
@@ -47,15 +47,15 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) {
|
||||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
|
||||
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
switch(status) {
|
||||
case GL_FRAMEBUFFER_COMPLETE_EXT:
|
||||
ILOG("Framebuffer verified complete.");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
ELOG("Framebuffer format not supported");
|
||||
break;
|
||||
default:
|
||||
FLOG("Other framebuffer error: %i", status);
|
||||
break;
|
||||
case GL_FRAMEBUFFER_COMPLETE_EXT:
|
||||
ILOG("Framebuffer verified complete.");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
ELOG("Framebuffer format not supported");
|
||||
break;
|
||||
default:
|
||||
FLOG("Other framebuffer error: %i", status);
|
||||
break;
|
||||
}
|
||||
// Unbind state we don't need
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
+70
-70
@@ -24,25 +24,25 @@ typedef char GLchar;
|
||||
static std::set<GLSLProgram *> active_programs;
|
||||
|
||||
bool CompileShader(const char *source, GLuint shader, const char *filename) {
|
||||
glShaderSource(shader, 1, &source, NULL);
|
||||
glCompileShader(shader);
|
||||
GLint success;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
if (!success) {
|
||||
glShaderSource(shader, 1, &source, NULL);
|
||||
glCompileShader(shader);
|
||||
GLint success;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
if (!success) {
|
||||
#define MAX_INFO_LOG_SIZE 2048
|
||||
GLchar infoLog[MAX_INFO_LOG_SIZE];
|
||||
GLchar infoLog[MAX_INFO_LOG_SIZE];
|
||||
GLsizei len;
|
||||
glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog);
|
||||
glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog);
|
||||
infoLog[len] = '\0';
|
||||
ELOG("Error in shader compilation of %s!\n", filename);
|
||||
ELOG("Info log: %s\n", infoLog);
|
||||
ELOG("Shader source:\n%s\n", (const char *)source);
|
||||
ELOG("Error in shader compilation of %s!\n", filename);
|
||||
ELOG("Info log: %s\n", infoLog);
|
||||
ELOG("Shader source:\n%s\n", (const char *)source);
|
||||
#ifdef ANDROID
|
||||
exit(1);
|
||||
exit(1);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
GLSLProgram *glsl_create(const char *vshader, const char *fshader) {
|
||||
@@ -50,7 +50,7 @@ GLSLProgram *glsl_create(const char *vshader, const char *fshader) {
|
||||
program->program_ = 0;
|
||||
program->vsh_ = 0;
|
||||
program->fsh_ = 0;
|
||||
strcpy(program->name, vshader + strlen(vshader) - 15);
|
||||
strcpy(program->name, vshader + strlen(vshader) - 15);
|
||||
strcpy(program->vshader_filename, vshader);
|
||||
strcpy(program->fshader_filename, fshader);
|
||||
if (glsl_recompile(program)) {
|
||||
@@ -65,8 +65,8 @@ bool glsl_up_to_date(GLSLProgram *program) {
|
||||
stat(program->vshader_filename, &vs);
|
||||
stat(program->fshader_filename, &fs);
|
||||
if (vs.st_mtime != program->vshader_mtime ||
|
||||
fs.st_mtime != program->fshader_mtime) {
|
||||
return false;
|
||||
fs.st_mtime != program->fshader_mtime) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
@@ -75,74 +75,74 @@ bool glsl_up_to_date(GLSLProgram *program) {
|
||||
void glsl_refresh() {
|
||||
ILOG("glsl_refresh()");
|
||||
for (std::set<GLSLProgram *>::const_iterator iter = active_programs.begin();
|
||||
iter != active_programs.end(); ++iter) {
|
||||
if (!glsl_up_to_date(*iter)) {
|
||||
glsl_recompile(*iter);
|
||||
}
|
||||
iter != active_programs.end(); ++iter) {
|
||||
if (!glsl_up_to_date(*iter)) {
|
||||
glsl_recompile(*iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool glsl_recompile(GLSLProgram *program) {
|
||||
struct stat vs, fs;
|
||||
if (0 == stat(program->vshader_filename, &vs))
|
||||
program->vshader_mtime = vs.st_mtime;
|
||||
else
|
||||
program->vshader_mtime = 0;
|
||||
program->vshader_mtime = vs.st_mtime;
|
||||
else
|
||||
program->vshader_mtime = 0;
|
||||
|
||||
if (0 == stat(program->fshader_filename, &fs))
|
||||
program->fshader_mtime = fs.st_mtime;
|
||||
else
|
||||
program->fshader_mtime = 0;
|
||||
program->fshader_mtime = fs.st_mtime;
|
||||
else
|
||||
program->fshader_mtime = 0;
|
||||
|
||||
size_t sz;
|
||||
char *vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz);
|
||||
char *vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz);
|
||||
if (!vsh_src) {
|
||||
ELOG("File missing: %s", vsh_src);
|
||||
return false;
|
||||
}
|
||||
char *fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz);
|
||||
char *fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz);
|
||||
if (!fsh_src) {
|
||||
ELOG("File missing: %s", fsh_src);
|
||||
delete [] vsh_src;
|
||||
return false;
|
||||
}
|
||||
|
||||
GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
|
||||
const GLchar *vsh_str = (const GLchar *)(vsh_src);
|
||||
if (!CompileShader(vsh_str, vsh, program->vshader_filename)) {
|
||||
GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
|
||||
const GLchar *vsh_str = (const GLchar *)(vsh_src);
|
||||
if (!CompileShader(vsh_str, vsh, program->vshader_filename)) {
|
||||
return false;
|
||||
}
|
||||
delete [] vsh_src;
|
||||
|
||||
const GLchar *fsh_str = (const GLchar *)(fsh_src);
|
||||
GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
const GLchar *fsh_str = (const GLchar *)(fsh_src);
|
||||
GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (!CompileShader(fsh_str, fsh, program->fshader_filename)) {
|
||||
glDeleteShader(vsh);
|
||||
return false;
|
||||
}
|
||||
delete [] fsh_src;
|
||||
delete [] fsh_src;
|
||||
|
||||
GLuint prog = glCreateProgram();
|
||||
glAttachShader(prog, vsh);
|
||||
glAttachShader(prog, fsh);
|
||||
glAttachShader(prog, vsh);
|
||||
glAttachShader(prog, fsh);
|
||||
|
||||
glLinkProgram(prog);
|
||||
glLinkProgram(prog);
|
||||
|
||||
GLint linkStatus;
|
||||
glGetProgramiv(prog, GL_LINK_STATUS, &linkStatus);
|
||||
if (linkStatus != GL_TRUE) {
|
||||
GLint bufLength = 0;
|
||||
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &bufLength);
|
||||
if (bufLength) {
|
||||
char* buf = new char[bufLength];
|
||||
glGetProgramInfoLog(prog, bufLength, NULL, buf);
|
||||
FLOG("Could not link program:\n %s", buf);
|
||||
delete [] buf; // we're dead!
|
||||
}
|
||||
GLint linkStatus;
|
||||
glGetProgramiv(prog, GL_LINK_STATUS, &linkStatus);
|
||||
if (linkStatus != GL_TRUE) {
|
||||
GLint bufLength = 0;
|
||||
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &bufLength);
|
||||
if (bufLength) {
|
||||
char* buf = new char[bufLength];
|
||||
glGetProgramInfoLog(prog, bufLength, NULL, buf);
|
||||
FLOG("Could not link program:\n %s", buf);
|
||||
delete [] buf; // we're dead!
|
||||
}
|
||||
glDeleteShader(vsh);
|
||||
glDeleteShader(fsh);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Destroy the old program, if any.
|
||||
if (program->program_) {
|
||||
@@ -153,23 +153,23 @@ bool glsl_recompile(GLSLProgram *program) {
|
||||
program->vsh_ = vsh;
|
||||
program->fsh_ = vsh;
|
||||
|
||||
program->sampler0 = glGetUniformLocation(program->program_, "sampler0");
|
||||
program->sampler1 = glGetUniformLocation(program->program_, "sampler1");
|
||||
program->sampler0 = glGetUniformLocation(program->program_, "sampler0");
|
||||
program->sampler1 = glGetUniformLocation(program->program_, "sampler1");
|
||||
|
||||
program->a_position = glGetAttribLocation(program->program_, "a_position");
|
||||
program->a_color = glGetAttribLocation(program->program_, "a_color");
|
||||
program->a_normal = glGetAttribLocation(program->program_, "a_normal");
|
||||
program->a_texcoord0 = glGetAttribLocation(program->program_, "a_texcoord0");
|
||||
program->a_texcoord1 = glGetAttribLocation(program->program_, "a_texcoord1");
|
||||
program->a_position = glGetAttribLocation(program->program_, "a_position");
|
||||
program->a_color = glGetAttribLocation(program->program_, "a_color");
|
||||
program->a_normal = glGetAttribLocation(program->program_, "a_normal");
|
||||
program->a_texcoord0 = glGetAttribLocation(program->program_, "a_texcoord0");
|
||||
program->a_texcoord1 = glGetAttribLocation(program->program_, "a_texcoord1");
|
||||
|
||||
program->u_worldviewproj = glGetUniformLocation(program->program_, "u_worldviewproj");
|
||||
program->u_world = glGetUniformLocation(program->program_, "u_world");
|
||||
program->u_viewproj = glGetUniformLocation(program->program_, "u_viewproj");
|
||||
program->u_fog = glGetUniformLocation(program->program_, "u_fog");
|
||||
program->u_sundir = glGetUniformLocation(program->program_, "u_sundir");
|
||||
program->u_camerapos = glGetUniformLocation(program->program_, "u_camerapos");
|
||||
program->u_worldviewproj = glGetUniformLocation(program->program_, "u_worldviewproj");
|
||||
program->u_world = glGetUniformLocation(program->program_, "u_world");
|
||||
program->u_viewproj = glGetUniformLocation(program->program_, "u_viewproj");
|
||||
program->u_fog = glGetUniformLocation(program->program_, "u_fog");
|
||||
program->u_sundir = glGetUniformLocation(program->program_, "u_sundir");
|
||||
program->u_camerapos = glGetUniformLocation(program->program_, "u_camerapos");
|
||||
|
||||
//ILOG("Shader compilation success: %s %s",
|
||||
//ILOG("Shader compilation success: %s %s",
|
||||
// program->vshader_filename,
|
||||
// program->fshader_filename);
|
||||
return true;
|
||||
@@ -194,17 +194,17 @@ int glsl_uniform_loc(const GLSLProgram *program, const char *name) {
|
||||
|
||||
void glsl_destroy(GLSLProgram *program) {
|
||||
unregister_gl_resource_holder(program);
|
||||
glDeleteShader(program->vsh_);
|
||||
glDeleteShader(program->fsh_);
|
||||
glDeleteProgram(program->program_);
|
||||
glDeleteShader(program->vsh_);
|
||||
glDeleteShader(program->fsh_);
|
||||
glDeleteProgram(program->program_);
|
||||
active_programs.erase(program);
|
||||
delete program;
|
||||
}
|
||||
|
||||
void glsl_bind(const GLSLProgram *program) {
|
||||
glUseProgram(program->program_);
|
||||
glUseProgram(program->program_);
|
||||
}
|
||||
|
||||
void glsl_unbind() {
|
||||
glUseProgram(0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
+47
-47
@@ -3,69 +3,69 @@
|
||||
#include "gfx_es2/vertex_format.h"
|
||||
|
||||
static const GLuint formatLookup[16] = {
|
||||
GL_FLOAT,
|
||||
0, //GL_HALF_FLOAT_EXT,
|
||||
GL_UNSIGNED_SHORT,
|
||||
GL_UNSIGNED_BYTE,
|
||||
0, //GL_UNSIGNED_INT_10_10_10_2,
|
||||
0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
GL_FLOAT,
|
||||
0, //GL_HALF_FLOAT_EXT,
|
||||
GL_UNSIGNED_SHORT,
|
||||
GL_UNSIGNED_BYTE,
|
||||
0, //GL_UNSIGNED_INT_10_10_10_2,
|
||||
0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
void SetVertexFormat(const GLSLProgram *program, uint32_t vertexFormat) {
|
||||
// First special case our favorites
|
||||
if (vertexFormat == (POS_FLOAT | NRM_FLOAT | UV0_FLOAT)) {
|
||||
const int vertexSize = 3*4 + 3*4 + 2*4;
|
||||
glUniform1i(program->sampler0, 0);
|
||||
glEnableVertexAttribArray(program->a_position);
|
||||
glEnableVertexAttribArray(program->a_normal);
|
||||
glEnableVertexAttribArray(program->a_texcoord0);
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0);
|
||||
glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24);
|
||||
return;
|
||||
}
|
||||
|
||||
// Then have generic code here.
|
||||
// First special case our favorites
|
||||
if (vertexFormat == (POS_FLOAT | NRM_FLOAT | UV0_FLOAT)) {
|
||||
const int vertexSize = 3*4 + 3*4 + 2*4;
|
||||
glUniform1i(program->sampler0, 0);
|
||||
glEnableVertexAttribArray(program->a_position);
|
||||
glEnableVertexAttribArray(program->a_normal);
|
||||
glEnableVertexAttribArray(program->a_texcoord0);
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0);
|
||||
glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24);
|
||||
return;
|
||||
}
|
||||
|
||||
// Then have generic code here.
|
||||
|
||||
|
||||
int vertexSize = 0;
|
||||
int vertexSize = 0;
|
||||
|
||||
FLOG("TODO: Write generic code.");
|
||||
FLOG("TODO: Write generic code.");
|
||||
|
||||
if (vertexFormat & UV0_MASK) {
|
||||
glUniform1i(program->sampler0, 0);
|
||||
}
|
||||
if (vertexFormat & UV0_MASK) {
|
||||
glUniform1i(program->sampler0, 0);
|
||||
}
|
||||
|
||||
glEnableVertexAttribArray(program->a_position);
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0);
|
||||
if (vertexFormat & NRM_MASK) {
|
||||
glEnableVertexAttribArray(program->a_normal);
|
||||
glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12);
|
||||
}
|
||||
if (vertexFormat & UV0_MASK) {
|
||||
glEnableVertexAttribArray(program->a_texcoord0);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24);
|
||||
}
|
||||
if (vertexFormat & UV1_MASK) {
|
||||
glEnableVertexAttribArray(program->a_texcoord1);
|
||||
glVertexAttribPointer(program->a_texcoord1, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24);
|
||||
}
|
||||
if (vertexFormat & RGBA_MASK) {
|
||||
glEnableVertexAttribArray(program->a_color);
|
||||
glVertexAttribPointer(program->a_color, 4, GL_FLOAT, GL_FALSE, vertexSize, (void *)28);
|
||||
}
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0);
|
||||
if (vertexFormat & NRM_MASK) {
|
||||
glEnableVertexAttribArray(program->a_normal);
|
||||
glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12);
|
||||
}
|
||||
if (vertexFormat & UV0_MASK) {
|
||||
glEnableVertexAttribArray(program->a_texcoord0);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24);
|
||||
}
|
||||
if (vertexFormat & UV1_MASK) {
|
||||
glEnableVertexAttribArray(program->a_texcoord1);
|
||||
glVertexAttribPointer(program->a_texcoord1, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24);
|
||||
}
|
||||
if (vertexFormat & RGBA_MASK) {
|
||||
glEnableVertexAttribArray(program->a_color);
|
||||
glVertexAttribPointer(program->a_color, 4, GL_FLOAT, GL_FALSE, vertexSize, (void *)28);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Save state so that we can get rid of this.
|
||||
void UnsetVertexFormat(const GLSLProgram *program, uint32 vertexFormat) {
|
||||
glDisableVertexAttribArray(program->a_position);
|
||||
if (vertexFormat & NRM_MASK)
|
||||
glDisableVertexAttribArray(program->a_normal);
|
||||
glDisableVertexAttribArray(program->a_normal);
|
||||
if (vertexFormat & UV0_MASK)
|
||||
glDisableVertexAttribArray(program->a_texcoord0);
|
||||
glDisableVertexAttribArray(program->a_texcoord0);
|
||||
if (vertexFormat & UV1_MASK)
|
||||
glDisableVertexAttribArray(program->a_texcoord1);
|
||||
glDisableVertexAttribArray(program->a_texcoord1);
|
||||
if (vertexFormat & RGBA_MASK)
|
||||
glDisableVertexAttribArray(program->a_color);
|
||||
glDisableVertexAttribArray(program->a_color);
|
||||
}
|
||||
+30
-30
@@ -6,42 +6,42 @@
|
||||
|
||||
// Vertex format flags
|
||||
enum VtxFmt {
|
||||
POS_FLOAT = 1,
|
||||
POS_FLOAT16 = 2,
|
||||
POS_UINT16 = 3,
|
||||
POS_UINT8 = 4,
|
||||
POS_101010 = 5,
|
||||
POS_FLOAT = 1,
|
||||
POS_FLOAT16 = 2,
|
||||
POS_UINT16 = 3,
|
||||
POS_UINT8 = 4,
|
||||
POS_101010 = 5,
|
||||
|
||||
NRM_FLOAT = 1 << 4,
|
||||
NRM_FLOAT16 = 2 << 4,
|
||||
NRM_SINT16 = 3 << 4,
|
||||
NRM_UINT8 = 4 << 4,
|
||||
NRM_101010 = 5 << 4,
|
||||
NRM_FLOAT = 1 << 4,
|
||||
NRM_FLOAT16 = 2 << 4,
|
||||
NRM_SINT16 = 3 << 4,
|
||||
NRM_UINT8 = 4 << 4,
|
||||
NRM_101010 = 5 << 4,
|
||||
|
||||
TANGENT_FLOAT = 1 << 8,
|
||||
//....
|
||||
TANGENT_FLOAT = 1 << 8,
|
||||
//....
|
||||
|
||||
UV0_NONE = 1 << 12,
|
||||
UV0_FLOAT = 1 << 12,
|
||||
// ....
|
||||
UV1_NONE = 1 << 16,
|
||||
UV1_FLOAT = 1 << 16,
|
||||
UV0_NONE = 1 << 12,
|
||||
UV0_FLOAT = 1 << 12,
|
||||
// ....
|
||||
UV1_NONE = 1 << 16,
|
||||
UV1_FLOAT = 1 << 16,
|
||||
|
||||
RGBA_NONE = 0 << 20,
|
||||
RGBA_FLOAT = 1 << 20,
|
||||
RGBA_FLOAT16 = 2 << 20,
|
||||
RGBA_UINT16 = 3 << 20,
|
||||
RGBA_UINT8 = 4 << 20,
|
||||
RGBA_101010 = 5 << 20,
|
||||
RGBA_NONE = 0 << 20,
|
||||
RGBA_FLOAT = 1 << 20,
|
||||
RGBA_FLOAT16 = 2 << 20,
|
||||
RGBA_UINT16 = 3 << 20,
|
||||
RGBA_UINT8 = 4 << 20,
|
||||
RGBA_101010 = 5 << 20,
|
||||
|
||||
POS_MASK = 0x0000000F,
|
||||
NRM_MASK = 0x000000F0,
|
||||
TANGENT_MASK = 0x00000F00,
|
||||
UV0_MASK = 0x0000F000,
|
||||
UV1_MASK = 0x000F0000,
|
||||
RGBA_MASK = 0x00F00000,
|
||||
POS_MASK = 0x0000000F,
|
||||
NRM_MASK = 0x000000F0,
|
||||
TANGENT_MASK = 0x00000F00,
|
||||
UV0_MASK = 0x0000F000,
|
||||
UV1_MASK = 0x000F0000,
|
||||
RGBA_MASK = 0x00F00000,
|
||||
|
||||
// Can add more here, such as a generic AUX or something. Don't know what to use it for though. Hardness for cloth sim?
|
||||
// Can add more here, such as a generic AUX or something. Don't know what to use it for though. Hardness for cloth sim?
|
||||
};
|
||||
|
||||
struct GLSLProgram;
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
#ifndef _GFX_SURFACE
|
||||
#define _GFX_SURFACE
|
||||
|
||||
// UNUSED
|
||||
|
||||
|
||||
enum SurfaceFormats {
|
||||
SURF_ARGB,
|
||||
SURF_YUV,
|
||||
};
|
||||
|
||||
struct cairo_surface_t;
|
||||
|
||||
class Surface {
|
||||
public:
|
||||
Surface(int width, int height);
|
||||
|
||||
// In case of YUV, U and V channels have half size, rounded UP.
|
||||
int height() const { return height_; }
|
||||
int width() const { return width_; }
|
||||
int pitch() const { return pitch_; }
|
||||
|
||||
int half_width() const { return (width_ + 1) >> 1; }
|
||||
int half_height() const { return (height_ + 1) >> 1; }
|
||||
|
||||
cairo_surface_t *CreateCairoSurface();
|
||||
private:
|
||||
uint8 *data_;
|
||||
int width_;
|
||||
int height_;
|
||||
int pitch_;
|
||||
};
|
||||
|
||||
#endif
|
||||
+70
-70
@@ -8,42 +8,42 @@
|
||||
#include "file/vfs.h"
|
||||
|
||||
int ezuncompress(unsigned char* pDest, long* pnDestLen, const unsigned char* pSrc, long nSrcLen) {
|
||||
z_stream stream;
|
||||
stream.next_in = (Bytef*)pSrc;
|
||||
stream.avail_in = (uInt)nSrcLen;
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != (uLong)nSrcLen) return Z_BUF_ERROR;
|
||||
z_stream stream;
|
||||
stream.next_in = (Bytef*)pSrc;
|
||||
stream.avail_in = (uInt)nSrcLen;
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != (uLong)nSrcLen) return Z_BUF_ERROR;
|
||||
|
||||
uInt destlen = (uInt)*pnDestLen;
|
||||
if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
uInt destlen = (uInt)*pnDestLen;
|
||||
if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
|
||||
int err = inflateInit(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
int err = inflateInit(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
int nExtraChunks = 0;
|
||||
do {
|
||||
stream.next_out = pDest;
|
||||
stream.avail_out = destlen;
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err == Z_STREAM_END )
|
||||
break;
|
||||
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
|
||||
err = Z_DATA_ERROR;
|
||||
if (err != Z_BUF_ERROR) {
|
||||
inflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
nExtraChunks += 1;
|
||||
} while (stream.avail_out == 0);
|
||||
int nExtraChunks = 0;
|
||||
do {
|
||||
stream.next_out = pDest;
|
||||
stream.avail_out = destlen;
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err == Z_STREAM_END )
|
||||
break;
|
||||
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
|
||||
err = Z_DATA_ERROR;
|
||||
if (err != Z_BUF_ERROR) {
|
||||
inflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
nExtraChunks += 1;
|
||||
} while (stream.avail_out == 0);
|
||||
|
||||
*pnDestLen = stream.total_out;
|
||||
*pnDestLen = stream.total_out;
|
||||
|
||||
err = inflateEnd(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
err = inflateEnd(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
return nExtraChunks ? Z_BUF_ERROR : Z_OK;
|
||||
return nExtraChunks ? Z_BUF_ERROR : Z_OK;
|
||||
}
|
||||
|
||||
static const char magic[5] = "ZIMG";
|
||||
@@ -57,13 +57,13 @@ static unsigned int log2i(unsigned int val) {
|
||||
}
|
||||
|
||||
int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags, uint8 **image) {
|
||||
if (zim[0] != 'Z' || zim[1] != 'I' || zim[2] != 'M' || zim[3] != 'G') {
|
||||
ELOG("Not a ZIM file");
|
||||
if (zim[0] != 'Z' || zim[1] != 'I' || zim[2] != 'M' || zim[3] != 'G') {
|
||||
ELOG("Not a ZIM file");
|
||||
return 0;
|
||||
}
|
||||
memcpy(width, zim + 4, 4);
|
||||
memcpy(height, zim + 8, 4);
|
||||
memcpy(flags, zim + 12, 4);
|
||||
}
|
||||
memcpy(width, zim + 4, 4);
|
||||
memcpy(height, zim + 8, 4);
|
||||
memcpy(flags, zim + 12, 4);
|
||||
|
||||
int num_levels = 1;
|
||||
int image_data_size[ZIM_MAX_MIP_LEVELS];
|
||||
@@ -76,14 +76,14 @@ int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags,
|
||||
width[i] = width[i-1] / 2;
|
||||
height[i] = height[i-1] / 2;
|
||||
}
|
||||
switch (*flags & ZIM_FORMAT_MASK) {
|
||||
case ZIM_RGBA8888:
|
||||
image_data_size[i] = width[i] * height[i] * 4;
|
||||
break;
|
||||
case ZIM_RGBA4444:
|
||||
switch (*flags & ZIM_FORMAT_MASK) {
|
||||
case ZIM_RGBA8888:
|
||||
image_data_size[i] = width[i] * height[i] * 4;
|
||||
break;
|
||||
case ZIM_RGBA4444:
|
||||
case ZIM_RGB565:
|
||||
image_data_size[i] = width[i] * height[i] * 2;
|
||||
break;
|
||||
image_data_size[i] = width[i] * height[i] * 2;
|
||||
break;
|
||||
case ZIM_ETC1:
|
||||
{
|
||||
int data_width = width[i];
|
||||
@@ -93,47 +93,47 @@ int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags,
|
||||
image_data_size[i] = data_width * data_height / 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ELOG("Invalid ZIM format %i", *flags & ZIM_FORMAT_MASK);
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
ELOG("Invalid ZIM format %i", *flags & ZIM_FORMAT_MASK);
|
||||
return 0;
|
||||
}
|
||||
total_data_size += image_data_size[i];
|
||||
}
|
||||
|
||||
image[0] = (uint8 *)malloc(total_data_size);
|
||||
image[0] = (uint8 *)malloc(total_data_size);
|
||||
for (int i = 1; i < num_levels; i++) {
|
||||
image[i] = image[i-1] + image_data_size[i-1];
|
||||
}
|
||||
|
||||
if (*flags & ZIM_ZLIB_COMPRESSED) {
|
||||
long outlen = total_data_size;
|
||||
if (Z_OK != ezuncompress(*image, &outlen, (unsigned char *)(zim + 16), datasize - 16)) {
|
||||
free(*image);
|
||||
*image = 0;
|
||||
return 0;
|
||||
}
|
||||
if (outlen != total_data_size) {
|
||||
ELOG("Wrong size data in ZIM: %i vs %i", (int)outlen, (int)total_data_size);
|
||||
}
|
||||
long outlen = total_data_size;
|
||||
if (Z_OK != ezuncompress(*image, &outlen, (unsigned char *)(zim + 16), datasize - 16)) {
|
||||
free(*image);
|
||||
*image = 0;
|
||||
return 0;
|
||||
}
|
||||
if (outlen != total_data_size) {
|
||||
ELOG("Wrong size data in ZIM: %i vs %i", (int)outlen, (int)total_data_size);
|
||||
}
|
||||
} else {
|
||||
memcpy(*image, zim + 16, datasize - 16);
|
||||
if (datasize - 16 != total_data_size) {
|
||||
ELOG("Wrong size data in ZIM: %i vs %i", (int)(datasize-16), (int)total_data_size);
|
||||
ELOG("Wrong size data in ZIM: %i vs %i", (int)(datasize-16), (int)total_data_size);
|
||||
}
|
||||
}
|
||||
return num_levels;
|
||||
return num_levels;
|
||||
}
|
||||
|
||||
int LoadZIM(const char *filename, int *width, int *height, int *format, uint8_t **image) {
|
||||
size_t size;
|
||||
uint8_t *buffer = VFSReadFile(filename, &size);
|
||||
if (!buffer) {
|
||||
return 0;
|
||||
}
|
||||
int retval = LoadZIMPtr(buffer, size, width, height, format, image);
|
||||
if (!retval) {
|
||||
ELOG("Not a valid ZIM file: %s", filename);
|
||||
}
|
||||
delete [] buffer;
|
||||
return retval;
|
||||
size_t size;
|
||||
uint8_t *buffer = VFSReadFile(filename, &size);
|
||||
if (!buffer) {
|
||||
return 0;
|
||||
}
|
||||
int retval = LoadZIMPtr(buffer, size, width, height, format, image);
|
||||
if (!retval) {
|
||||
ELOG("Not a valid ZIM file: %s", filename);
|
||||
}
|
||||
delete [] buffer;
|
||||
return retval;
|
||||
}
|
||||
+134
-134
@@ -8,9 +8,9 @@
|
||||
static const char magic[5] = "ZIMG";
|
||||
|
||||
/*int num_levels = 1;
|
||||
if (flags & ZIM_HAS_MIPS) {
|
||||
num_levels = log2i(width > height ? width : height);
|
||||
}*/
|
||||
if (flags & ZIM_HAS_MIPS) {
|
||||
num_levels = log2i(width > height ? width : height);
|
||||
}*/
|
||||
static unsigned int log2i(unsigned int val) {
|
||||
unsigned int ret = -1;
|
||||
while (val != 0) {
|
||||
@@ -21,46 +21,46 @@ static unsigned int log2i(unsigned int val) {
|
||||
|
||||
|
||||
int ezcompress(unsigned char* pDest, long* pnDestLen, const unsigned char* pSrc, long nSrcLen) {
|
||||
z_stream stream;
|
||||
int err;
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
int nExtraChunks;
|
||||
uInt destlen;
|
||||
int nExtraChunks;
|
||||
uInt destlen;
|
||||
|
||||
stream.next_in = (Bytef*)pSrc;
|
||||
stream.avail_in = (uInt)nSrcLen;
|
||||
stream.next_in = (Bytef*)pSrc;
|
||||
stream.avail_in = (uInt)nSrcLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != nSrcLen) return Z_BUF_ERROR;
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != nSrcLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
destlen = (uInt)*pnDestLen;
|
||||
if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
destlen = (uInt)*pnDestLen;
|
||||
if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
|
||||
if (err != Z_OK) return err;
|
||||
nExtraChunks = 0;
|
||||
do {
|
||||
stream.next_out = pDest;
|
||||
stream.avail_out = destlen;
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err == Z_STREAM_END )
|
||||
break;
|
||||
if (err != Z_OK) {
|
||||
deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
nExtraChunks += 1;
|
||||
} while (stream.avail_out == 0);
|
||||
err = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
|
||||
if (err != Z_OK) return err;
|
||||
nExtraChunks = 0;
|
||||
do {
|
||||
stream.next_out = pDest;
|
||||
stream.avail_out = destlen;
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err == Z_STREAM_END )
|
||||
break;
|
||||
if (err != Z_OK) {
|
||||
deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
nExtraChunks += 1;
|
||||
} while (stream.avail_out == 0);
|
||||
|
||||
*pnDestLen = stream.total_out;
|
||||
*pnDestLen = stream.total_out;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
err = deflateEnd(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
return nExtraChunks ? Z_BUF_ERROR : Z_OK;
|
||||
return nExtraChunks ? Z_BUF_ERROR : Z_OK;
|
||||
}
|
||||
|
||||
inline int clamp16(int x) { if (x < 0) return 0; if (x > 15) return 15; return x; }
|
||||
@@ -78,95 +78,95 @@ bool ispowerof2 (int x) {
|
||||
|
||||
|
||||
void Convert(const uint8_t *image_data, int width, int height, int pitch, int flags,
|
||||
uint8_t **data, int *data_size) {
|
||||
// For 4444 and 565. Ordered dither matrix. looks really surprisingly good on cell phone screens at 4444.
|
||||
int dith[16] = {
|
||||
1, 9, 3, 11,
|
||||
13, 5, 15, 7,
|
||||
4, 12, 2, 10,
|
||||
16, 8, 14, 6
|
||||
};
|
||||
if ((flags & ZIM_DITHER) == 0) {
|
||||
for (int i = 0; i < 16; i++) { dith[i] = 8; }
|
||||
}
|
||||
switch (flags & ZIM_FORMAT_MASK) {
|
||||
case ZIM_RGBA8888:
|
||||
{
|
||||
*data_size = width * height * 4;
|
||||
*data = new uint8_t[width * height * 4];
|
||||
for (int y = 0; y < height; y++) {
|
||||
memcpy((*data) + y * width * 4, image_data + y * pitch, width * 4);
|
||||
uint8_t **data, int *data_size) {
|
||||
// For 4444 and 565. Ordered dither matrix. looks really surprisingly good on cell phone screens at 4444.
|
||||
int dith[16] = {
|
||||
1, 9, 3, 11,
|
||||
13, 5, 15, 7,
|
||||
4, 12, 2, 10,
|
||||
16, 8, 14, 6
|
||||
};
|
||||
if ((flags & ZIM_DITHER) == 0) {
|
||||
for (int i = 0; i < 16; i++) { dith[i] = 8; }
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZIM_ETC1: {
|
||||
// Check for power of 2
|
||||
if (!ispowerof2(width) || !ispowerof2(height)) {
|
||||
FLOG("Image must have power of 2 dimensions, %ix%i just isn't that.", width, height);
|
||||
}
|
||||
// Convert RGBX to ETC1 before saving.
|
||||
int blockw = width/4;
|
||||
int blockh = height/4;
|
||||
*data_size = blockw * blockh * 8;
|
||||
*data = new uint8_t[*data_size];
|
||||
#pragma omp parallel for
|
||||
for (int y = 0; y < blockh; y++) {
|
||||
for (int x = 0; x < blockw; x++) {
|
||||
CompressBlock(image_data + ((y * 4) * (pitch/4) + x * 4) * 4, width,
|
||||
(*data) + (blockw * y + x) * 8, 1);
|
||||
switch (flags & ZIM_FORMAT_MASK) {
|
||||
case ZIM_RGBA8888:
|
||||
{
|
||||
*data_size = width * height * 4;
|
||||
*data = new uint8_t[width * height * 4];
|
||||
for (int y = 0; y < height; y++) {
|
||||
memcpy((*data) + y * width * 4, image_data + y * pitch, width * 4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
width = blockw * 4;
|
||||
height = blockh * 4;
|
||||
break;
|
||||
}
|
||||
case ZIM_RGBA4444:
|
||||
{
|
||||
*data_size = width * height * 2;
|
||||
*data = new uint8_t[*data_size];
|
||||
uint16_t *dst = (uint16_t *)(*data);
|
||||
int i = 0;
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int dithval = dith[(x&3)+((y&0x3)<<2)] - 8;
|
||||
int r = clamp16((image_data[i * 4] + dithval) >> 4);
|
||||
int g = clamp16((image_data[i * 4 + 1] + dithval) >> 4);
|
||||
int b = clamp16((image_data[i * 4 + 2] + dithval) >> 4);
|
||||
int a = clamp16((image_data[i * 4 + 3] + dithval) >> 4); // really dither alpha?
|
||||
// Note: GL_UNSIGNED_SHORT_4_4_4_4, not GL_UNSIGNED_SHORT_4_4_4_4_REV
|
||||
*dst++ = (r << 12) | (g << 8) | (b << 4) | (a << 0);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZIM_RGB565:
|
||||
{
|
||||
*data_size = width * height * 2;
|
||||
case ZIM_ETC1: {
|
||||
// Check for power of 2
|
||||
if (!ispowerof2(width) || !ispowerof2(height)) {
|
||||
FLOG("Image must have power of 2 dimensions, %ix%i just isn't that.", width, height);
|
||||
}
|
||||
// Convert RGBX to ETC1 before saving.
|
||||
int blockw = width/4;
|
||||
int blockh = height/4;
|
||||
*data_size = blockw * blockh * 8;
|
||||
*data = new uint8_t[*data_size];
|
||||
uint16_t *dst = (uint16_t *)(*data);
|
||||
int i = 0;
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int dithval = dith[(x&3)+((y&0x3)<<2)] - 8;
|
||||
dithval = 0;
|
||||
int r = clamp32((image_data[i * 4] + dithval/2) >> 3);
|
||||
int g = clamp64((image_data[i * 4 + 1] + dithval/4) >> 2);
|
||||
int b = clamp32((image_data[i * 4 + 2] + dithval/2) >> 3);
|
||||
// Note: GL_UNSIGNED_SHORT_5_6_5, not GL_UNSIGNED_SHORT_5_6_5_REV
|
||||
*dst++ = (r << 11) | (g << 5) | (b);
|
||||
i++;
|
||||
#pragma omp parallel for
|
||||
for (int y = 0; y < blockh; y++) {
|
||||
for (int x = 0; x < blockw; x++) {
|
||||
CompressBlock(image_data + ((y * 4) * (pitch/4) + x * 4) * 4, width,
|
||||
(*data) + (blockw * y + x) * 8, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ELOG("Unhandled ZIM format %i", flags & ZIM_FORMAT_MASK);
|
||||
*data = 0;
|
||||
*data_size = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
width = blockw * 4;
|
||||
height = blockh * 4;
|
||||
break;
|
||||
}
|
||||
case ZIM_RGBA4444:
|
||||
{
|
||||
*data_size = width * height * 2;
|
||||
*data = new uint8_t[*data_size];
|
||||
uint16_t *dst = (uint16_t *)(*data);
|
||||
int i = 0;
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int dithval = dith[(x&3)+((y&0x3)<<2)] - 8;
|
||||
int r = clamp16((image_data[i * 4] + dithval) >> 4);
|
||||
int g = clamp16((image_data[i * 4 + 1] + dithval) >> 4);
|
||||
int b = clamp16((image_data[i * 4 + 2] + dithval) >> 4);
|
||||
int a = clamp16((image_data[i * 4 + 3] + dithval) >> 4); // really dither alpha?
|
||||
// Note: GL_UNSIGNED_SHORT_4_4_4_4, not GL_UNSIGNED_SHORT_4_4_4_4_REV
|
||||
*dst++ = (r << 12) | (g << 8) | (b << 4) | (a << 0);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZIM_RGB565:
|
||||
{
|
||||
*data_size = width * height * 2;
|
||||
*data = new uint8_t[*data_size];
|
||||
uint16_t *dst = (uint16_t *)(*data);
|
||||
int i = 0;
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int dithval = dith[(x&3)+((y&0x3)<<2)] - 8;
|
||||
dithval = 0;
|
||||
int r = clamp32((image_data[i * 4] + dithval/2) >> 3);
|
||||
int g = clamp64((image_data[i * 4 + 1] + dithval/4) >> 2);
|
||||
int b = clamp32((image_data[i * 4 + 2] + dithval/2) >> 3);
|
||||
// Note: GL_UNSIGNED_SHORT_5_6_5, not GL_UNSIGNED_SHORT_5_6_5_REV
|
||||
*dst++ = (r << 11) | (g << 5) | (b);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ELOG("Unhandled ZIM format %i", flags & ZIM_FORMAT_MASK);
|
||||
*data = 0;
|
||||
*data_size = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Deletes the old buffer.
|
||||
@@ -199,28 +199,28 @@ uint8_t *DownsampleBy2(const uint8_t *image, int width, int height, int pitch) {
|
||||
}
|
||||
|
||||
void SaveZIM(const char *filename, int width, int height, int pitch, int flags, const uint8_t *image_data) {
|
||||
FILE *f = fopen(filename, "wb");
|
||||
fwrite(magic, 1, 4, f);
|
||||
fwrite(&width, 1, 4, f);
|
||||
fwrite(&height, 1, 4, f);
|
||||
fwrite(&flags, 1, 4, f);
|
||||
FILE *f = fopen(filename, "wb");
|
||||
fwrite(magic, 1, 4, f);
|
||||
fwrite(&width, 1, 4, f);
|
||||
fwrite(&height, 1, 4, f);
|
||||
fwrite(&flags, 1, 4, f);
|
||||
|
||||
int num_levels = 1;
|
||||
if (flags & ZIM_HAS_MIPS) {
|
||||
num_levels = log2i(width > height ? height : width) + 1;
|
||||
}
|
||||
for (int i = 0; i < num_levels; i++) {
|
||||
uint8_t *data = 0;
|
||||
uint8_t *data = 0;
|
||||
int data_size;
|
||||
Convert(image_data, width, height, pitch, flags, &data, &data_size);
|
||||
if (flags & ZIM_ZLIB_COMPRESSED) {
|
||||
long dest_len = data_size * 2;
|
||||
uint8_t *dest = new uint8_t[dest_len];
|
||||
if (Z_OK == ezcompress(dest, &dest_len, data, data_size)) {
|
||||
fwrite(dest, 1, dest_len, f);
|
||||
} else {
|
||||
ELOG("Zlib compression failed.\n");
|
||||
}
|
||||
long dest_len = data_size * 2;
|
||||
uint8_t *dest = new uint8_t[dest_len];
|
||||
if (Z_OK == ezcompress(dest, &dest_len, data, data_size)) {
|
||||
fwrite(dest, 1, dest_len, f);
|
||||
} else {
|
||||
ELOG("Zlib compression failed.\n");
|
||||
}
|
||||
delete [] dest;
|
||||
} else {
|
||||
fwrite(data, 1, data_size, f);
|
||||
@@ -243,5 +243,5 @@ void SaveZIM(const char *filename, int width, int height, int pitch, int flags,
|
||||
}
|
||||
}
|
||||
delete [] image_data;
|
||||
fclose(f);
|
||||
fclose(f);
|
||||
}
|
||||
+35
-35
@@ -7,17 +7,17 @@
|
||||
namespace GestureDetector {
|
||||
|
||||
struct Finger {
|
||||
bool down;
|
||||
float X;
|
||||
float Y;
|
||||
float lastX;
|
||||
float lastY;
|
||||
float downX;
|
||||
float downY;
|
||||
float deltaX;
|
||||
float deltaY;
|
||||
float smoothDeltaX;
|
||||
float smoothDeltaY;
|
||||
bool down;
|
||||
float X;
|
||||
float Y;
|
||||
float lastX;
|
||||
float lastY;
|
||||
float downX;
|
||||
float downY;
|
||||
float deltaX;
|
||||
float deltaY;
|
||||
float smoothDeltaX;
|
||||
float smoothDeltaY;
|
||||
};
|
||||
|
||||
// State
|
||||
@@ -26,43 +26,43 @@ struct Finger {
|
||||
static Finger fingers[MAX_FINGERS];
|
||||
|
||||
void update(const InputState &state) {
|
||||
// Mouse / 1-finger-touch control.
|
||||
if (state.mouse_down[0]) {
|
||||
fingers[0].down = true;
|
||||
fingers[0].downX = state.mouse_x[0];
|
||||
fingers[0].downY = state.mouse_y[0];
|
||||
} else {
|
||||
fingers[0].down = false;
|
||||
}
|
||||
// Mouse / 1-finger-touch control.
|
||||
if (state.mouse_down[0]) {
|
||||
fingers[0].down = true;
|
||||
fingers[0].downX = state.mouse_x[0];
|
||||
fingers[0].downY = state.mouse_y[0];
|
||||
} else {
|
||||
fingers[0].down = false;
|
||||
}
|
||||
|
||||
fingers[0].lastX = fingers[0].X;
|
||||
fingers[0].lastY = fingers[0].Y;
|
||||
fingers[0].lastX = fingers[0].X;
|
||||
fingers[0].lastY = fingers[0].Y;
|
||||
|
||||
// TODO: real multitouch
|
||||
// TODO: real multitouch
|
||||
}
|
||||
|
||||
bool down(int i, float *xdelta, float *ydelta) {
|
||||
if (!fingers[i].down) {
|
||||
return false;
|
||||
}
|
||||
*xdelta = fingers[i].downX;
|
||||
*ydelta = fingers[i].downY;
|
||||
if (!fingers[i].down) {
|
||||
return false;
|
||||
}
|
||||
*xdelta = fingers[i].downX;
|
||||
*ydelta = fingers[i].downY;
|
||||
}
|
||||
|
||||
bool dragDistance(int i, float *xdelta, float *ydelta) {
|
||||
if (!fingers[i].down)
|
||||
return false;
|
||||
if (!fingers[i].down)
|
||||
return false;
|
||||
|
||||
*xdelta = fingers[i].X - fingers[i].downX;
|
||||
*ydelta = fingers[i].Y - fingers[i].downY;
|
||||
*xdelta = fingers[i].X - fingers[i].downX;
|
||||
*ydelta = fingers[i].Y - fingers[i].downY;
|
||||
}
|
||||
|
||||
bool dragDelta(int i, float *xdelta, float *ydelta) {
|
||||
if (!fingers[i].down)
|
||||
return false;
|
||||
if (!fingers[i].down)
|
||||
return false;
|
||||
|
||||
*xdelta = fingers[i].X - fingers[i].lastX;
|
||||
*ydelta = fingers[i].Y - fingers[i].lastY;
|
||||
*xdelta = fingers[i].X - fingers[i].lastX;
|
||||
*ydelta = fingers[i].Y - fingers[i].lastY;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,17 +5,17 @@
|
||||
|
||||
namespace GestureDetector
|
||||
{
|
||||
void update(const InputState &state);
|
||||
void update(const InputState &state);
|
||||
|
||||
bool down(int finger, float *xdown, float *ydown);
|
||||
bool down(int finger, float *xdown, float *ydown);
|
||||
|
||||
// x/ydelta is difference from current location to the start of the drag.
|
||||
// Returns true if button/finger is down, for convenience.
|
||||
bool dragDistance(int finger, float *xdelta, float *ydelta);
|
||||
|
||||
// x/ydelta is (smoothed?) difference from current location to the position from the last frame.
|
||||
// Returns true if button/finger is down, for convenience.
|
||||
bool dragDelta(int finger, float *xdelta, float *ydelta);
|
||||
// x/ydelta is difference from current location to the start of the drag.
|
||||
// Returns true if button/finger is down, for convenience.
|
||||
bool dragDistance(int finger, float *xdelta, float *ydelta);
|
||||
|
||||
// x/ydelta is (smoothed?) difference from current location to the position from the last frame.
|
||||
// Returns true if button/finger is down, for convenience.
|
||||
bool dragDelta(int finger, float *xdelta, float *ydelta);
|
||||
|
||||
|
||||
};
|
||||
+14
-14
@@ -21,22 +21,22 @@ enum {
|
||||
#ifndef MAX_POINTERS
|
||||
#define MAX_POINTERS 8
|
||||
#endif
|
||||
|
||||
|
||||
// Agglomeration of all possible inputs, and automatically computed
|
||||
// deltas where applicable.
|
||||
struct InputState {
|
||||
// Lock this whenever you access the data in this struct.
|
||||
mutable recursive_mutex lock;
|
||||
InputState()
|
||||
: pad_buttons(0),
|
||||
pad_last_buttons(0),
|
||||
pad_buttons_down(0),
|
||||
pad_buttons_up(0),
|
||||
mouse_valid(false),
|
||||
accelerometer_valid(false) {
|
||||
memset(mouse_down, 0, sizeof(mouse_down));
|
||||
memset(mouse_last, 0, sizeof(mouse_last));
|
||||
}
|
||||
// Lock this whenever you access the data in this struct.
|
||||
mutable recursive_mutex lock;
|
||||
InputState()
|
||||
: pad_buttons(0),
|
||||
pad_last_buttons(0),
|
||||
pad_buttons_down(0),
|
||||
pad_buttons_up(0),
|
||||
mouse_valid(false),
|
||||
accelerometer_valid(false) {
|
||||
memset(mouse_down, 0, sizeof(mouse_down));
|
||||
memset(mouse_last, 0, sizeof(mouse_last));
|
||||
}
|
||||
|
||||
// Gamepad style input
|
||||
int pad_buttons; // bitfield
|
||||
@@ -51,7 +51,7 @@ struct InputState {
|
||||
float pad_rtrigger;
|
||||
|
||||
// Mouse/touch style input
|
||||
// There are up to 8 mice / fingers.
|
||||
// There are up to 8 mice / fingers.
|
||||
volatile bool mouse_valid;
|
||||
|
||||
int mouse_x[MAX_POINTERS];
|
||||
|
||||
@@ -103,13 +103,13 @@ void JsonWriter::pop() {
|
||||
BlockType type = stack_.back().type;
|
||||
stack_.pop_back();
|
||||
switch (type) {
|
||||
case ARRAY:
|
||||
str_ << "\n" << indent() << "]";
|
||||
break;
|
||||
case DICT:
|
||||
str_ << "\n" << indent() << "}";
|
||||
break;
|
||||
case ARRAY:
|
||||
str_ << "\n" << indent() << "]";
|
||||
break;
|
||||
case DICT:
|
||||
str_ << "\n" << indent() << "}";
|
||||
break;
|
||||
}
|
||||
if (stack_.size() > 0)
|
||||
stack_.back().first = false;
|
||||
if (stack_.size() > 0)
|
||||
stack_.back().first = false;
|
||||
}
|
||||
+4
-4
@@ -17,14 +17,14 @@
|
||||
#include "base/basictypes.h"
|
||||
|
||||
class JsonWriter {
|
||||
public:
|
||||
public:
|
||||
JsonWriter();
|
||||
~JsonWriter();
|
||||
void begin();
|
||||
void end();
|
||||
void pushDict(const char *name);
|
||||
void pushArray(const char *name);
|
||||
void pop();
|
||||
void pop();
|
||||
void writeBool(bool value);
|
||||
void writeBool(const char *name, bool value);
|
||||
void writeInt(int value);
|
||||
@@ -38,7 +38,7 @@ class JsonWriter {
|
||||
return str_.str();
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
const char *indent(int n) const;
|
||||
const char *comma() const;
|
||||
const char *arrayComma() const;
|
||||
@@ -56,5 +56,5 @@ class JsonWriter {
|
||||
std::vector<StackEntry> stack_;
|
||||
std::ostringstream str_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JsonWriter);
|
||||
DISALLOW_COPY_AND_ASSIGN(JsonWriter);
|
||||
};
|
||||
+9
-9
@@ -5,18 +5,18 @@
|
||||
|
||||
template <class T>
|
||||
inline void delta(T *data, int length) {
|
||||
T prev = data[0];
|
||||
for (int i = 1; i < length; i++) {
|
||||
T temp = data[i] - prev;
|
||||
prev = data[i];
|
||||
data[i] = temp;
|
||||
}
|
||||
T prev = data[0];
|
||||
for (int i = 1; i < length; i++) {
|
||||
T temp = data[i] - prev;
|
||||
prev = data[i];
|
||||
data[i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void dedelta(T *data, int length) {
|
||||
for (int i = 1; i < length; i++) {
|
||||
data[i] += data[i - 1];
|
||||
}
|
||||
for (int i = 1; i < length; i++) {
|
||||
data[i] += data[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
+181
-181
@@ -14,189 +14,189 @@
|
||||
// no wait. http://code.google.com/p/math-neon/
|
||||
|
||||
void matrix_mul_4x4(Matrix4x4 &res, const Matrix4x4 &inA, const Matrix4x4 &inB) {
|
||||
res.xx = inA.xx*inB.xx + inA.xy*inB.yx + inA.xz*inB.zx + inA.xw*inB.wx;
|
||||
res.xy = inA.xx*inB.xy + inA.xy*inB.yy + inA.xz*inB.zy + inA.xw*inB.wy;
|
||||
res.xz = inA.xx*inB.xz + inA.xy*inB.yz + inA.xz*inB.zz + inA.xw*inB.wz;
|
||||
res.xw = inA.xx*inB.xw + inA.xy*inB.yw + inA.xz*inB.zw + inA.xw*inB.ww;
|
||||
|
||||
res.yx = inA.yx*inB.xx + inA.yy*inB.yx + inA.yz*inB.zx + inA.yw*inB.wx;
|
||||
res.yy = inA.yx*inB.xy + inA.yy*inB.yy + inA.yz*inB.zy + inA.yw*inB.wy;
|
||||
res.yz = inA.yx*inB.xz + inA.yy*inB.yz + inA.yz*inB.zz + inA.yw*inB.wz;
|
||||
res.yw = inA.yx*inB.xw + inA.yy*inB.yw + inA.yz*inB.zw + inA.yw*inB.ww;
|
||||
|
||||
res.zx = inA.zx*inB.xx + inA.zy*inB.yx + inA.zz*inB.zx + inA.zw*inB.wx;
|
||||
res.zy = inA.zx*inB.xy + inA.zy*inB.yy + inA.zz*inB.zy + inA.zw*inB.wy;
|
||||
res.zz = inA.zx*inB.xz + inA.zy*inB.yz + inA.zz*inB.zz + inA.zw*inB.wz;
|
||||
res.zw = inA.zx*inB.xw + inA.zy*inB.yw + inA.zz*inB.zw + inA.zw*inB.ww;
|
||||
|
||||
res.wx = inA.wx*inB.xx + inA.wy*inB.yx + inA.wz*inB.zx + inA.ww*inB.wx;
|
||||
res.wy = inA.wx*inB.xy + inA.wy*inB.yy + inA.wz*inB.zy + inA.ww*inB.wy;
|
||||
res.wz = inA.wx*inB.xz + inA.wy*inB.yz + inA.wz*inB.zz + inA.ww*inB.wz;
|
||||
res.ww = inA.wx*inB.xw + inA.wy*inB.yw + inA.wz*inB.zw + inA.ww*inB.ww;
|
||||
res.xx = inA.xx*inB.xx + inA.xy*inB.yx + inA.xz*inB.zx + inA.xw*inB.wx;
|
||||
res.xy = inA.xx*inB.xy + inA.xy*inB.yy + inA.xz*inB.zy + inA.xw*inB.wy;
|
||||
res.xz = inA.xx*inB.xz + inA.xy*inB.yz + inA.xz*inB.zz + inA.xw*inB.wz;
|
||||
res.xw = inA.xx*inB.xw + inA.xy*inB.yw + inA.xz*inB.zw + inA.xw*inB.ww;
|
||||
|
||||
res.yx = inA.yx*inB.xx + inA.yy*inB.yx + inA.yz*inB.zx + inA.yw*inB.wx;
|
||||
res.yy = inA.yx*inB.xy + inA.yy*inB.yy + inA.yz*inB.zy + inA.yw*inB.wy;
|
||||
res.yz = inA.yx*inB.xz + inA.yy*inB.yz + inA.yz*inB.zz + inA.yw*inB.wz;
|
||||
res.yw = inA.yx*inB.xw + inA.yy*inB.yw + inA.yz*inB.zw + inA.yw*inB.ww;
|
||||
|
||||
res.zx = inA.zx*inB.xx + inA.zy*inB.yx + inA.zz*inB.zx + inA.zw*inB.wx;
|
||||
res.zy = inA.zx*inB.xy + inA.zy*inB.yy + inA.zz*inB.zy + inA.zw*inB.wy;
|
||||
res.zz = inA.zx*inB.xz + inA.zy*inB.yz + inA.zz*inB.zz + inA.zw*inB.wz;
|
||||
res.zw = inA.zx*inB.xw + inA.zy*inB.yw + inA.zz*inB.zw + inA.zw*inB.ww;
|
||||
|
||||
res.wx = inA.wx*inB.xx + inA.wy*inB.yx + inA.wz*inB.zx + inA.ww*inB.wx;
|
||||
res.wy = inA.wx*inB.xy + inA.wy*inB.yy + inA.wz*inB.zy + inA.ww*inB.wy;
|
||||
res.wz = inA.wx*inB.xz + inA.wy*inB.yz + inA.wz*inB.zz + inA.ww*inB.wz;
|
||||
res.ww = inA.wx*inB.xw + inA.wy*inB.yw + inA.wz*inB.zw + inA.ww*inB.ww;
|
||||
}
|
||||
|
||||
Matrix4x4 Matrix4x4::simpleInverse() const {
|
||||
Matrix4x4 out;
|
||||
out.xx = xx;
|
||||
out.xy = yx;
|
||||
out.xz = zx;
|
||||
|
||||
out.yx = xy;
|
||||
out.yy = yy;
|
||||
out.yz = zy;
|
||||
|
||||
out.zx = xz;
|
||||
out.zy = yz;
|
||||
out.zz = zz;
|
||||
|
||||
out.wx = -(xx * wx + xy * wy + xz * wz);
|
||||
out.wy = -(yx * wx + yy * wy + yz * wz);
|
||||
out.wz = -(zx * wx + zy * wy + zz * wz);
|
||||
|
||||
out.xw = 0.0f;
|
||||
out.yw = 0.0f;
|
||||
out.zw = 0.0f;
|
||||
out.ww = 1.0f;
|
||||
Matrix4x4 out;
|
||||
out.xx = xx;
|
||||
out.xy = yx;
|
||||
out.xz = zx;
|
||||
|
||||
return out;
|
||||
out.yx = xy;
|
||||
out.yy = yy;
|
||||
out.yz = zy;
|
||||
|
||||
out.zx = xz;
|
||||
out.zy = yz;
|
||||
out.zz = zz;
|
||||
|
||||
out.wx = -(xx * wx + xy * wy + xz * wz);
|
||||
out.wy = -(yx * wx + yy * wy + yz * wz);
|
||||
out.wz = -(zx * wx + zy * wy + zz * wz);
|
||||
|
||||
out.xw = 0.0f;
|
||||
out.yw = 0.0f;
|
||||
out.zw = 0.0f;
|
||||
out.ww = 1.0f;
|
||||
|
||||
return out;
|
||||
}
|
||||
Matrix4x4 Matrix4x4::transpose() const
|
||||
{
|
||||
Matrix4x4 out;
|
||||
out.xx = xx;out.xy = yx;out.xz = zx;out.xw = wx;
|
||||
out.yx = xy;out.yy = yy;out.yz = zy;out.yw = wy;
|
||||
out.zx = xz;out.zy = yz;out.zz = zz;out.zw = wz;
|
||||
out.wx = xw;out.wy = yw;out.wz = zw;out.ww = ww;
|
||||
return out;
|
||||
Matrix4x4 out;
|
||||
out.xx = xx;out.xy = yx;out.xz = zx;out.xw = wx;
|
||||
out.yx = xy;out.yy = yy;out.yz = zy;out.yw = wy;
|
||||
out.zx = xz;out.zy = yz;out.zz = zz;out.zw = wz;
|
||||
out.wx = xw;out.wy = yw;out.wz = zw;out.ww = ww;
|
||||
return out;
|
||||
}
|
||||
|
||||
Matrix4x4 Matrix4x4::operator * (const Matrix4x4 &other) const
|
||||
{
|
||||
Matrix4x4 temp;
|
||||
matrix_mul_4x4(temp, *this, other);
|
||||
return temp;
|
||||
Matrix4x4 temp;
|
||||
matrix_mul_4x4(temp, *this, other);
|
||||
return temp;
|
||||
}
|
||||
|
||||
Matrix4x4 Matrix4x4::inverse() const {
|
||||
Matrix4x4 temp;
|
||||
float dW = 1.0f / (xx*(yy*zz - yz*zy) - xy*(yx*zz - yz*zx) - xz*(yy*zx - yx*zy));
|
||||
|
||||
temp.xx = (yy*zz - yz*zy) * dW;
|
||||
temp.xy = (xz*zy - xy*zz) * dW;
|
||||
temp.xz = (xy*yz - xz*yy) * dW;
|
||||
temp.xw = xw;
|
||||
|
||||
temp.yx = (yz*zx - yx*zz) * dW;
|
||||
temp.yy = (xx*zz - xz*zx) * dW;
|
||||
temp.yz = (xz*yx - xx*zx) * dW;
|
||||
temp.yw = yw;
|
||||
|
||||
temp.zx = (yx*zy - yy*zx) * dW;
|
||||
temp.zy = (xy*zx - xx*zy) * dW;
|
||||
temp.zz = (xx*yy - xy*yx) * dW;
|
||||
temp.zw = zw;
|
||||
|
||||
temp.wx = (yy*(zx*wz - zz*wx) + yz*(zy*wx - zx*wy) - yx*(zy*wz - zz*wy)) * dW;
|
||||
temp.wy = (xx*(zy*wz - zz*wy) + xy*(zz*wx - zx*wz) + xz*(zx*wy - zy*wx)) * dW;
|
||||
temp.wz = (xy*(yx*wz - yz*wx) + xz*(yy*wx - yx*wy) - xx*(yy*wz - yz*wy)) * dW;
|
||||
temp.ww = ww;
|
||||
|
||||
return temp;
|
||||
Matrix4x4 temp;
|
||||
float dW = 1.0f / (xx*(yy*zz - yz*zy) - xy*(yx*zz - yz*zx) - xz*(yy*zx - yx*zy));
|
||||
|
||||
temp.xx = (yy*zz - yz*zy) * dW;
|
||||
temp.xy = (xz*zy - xy*zz) * dW;
|
||||
temp.xz = (xy*yz - xz*yy) * dW;
|
||||
temp.xw = xw;
|
||||
|
||||
temp.yx = (yz*zx - yx*zz) * dW;
|
||||
temp.yy = (xx*zz - xz*zx) * dW;
|
||||
temp.yz = (xz*yx - xx*zx) * dW;
|
||||
temp.yw = yw;
|
||||
|
||||
temp.zx = (yx*zy - yy*zx) * dW;
|
||||
temp.zy = (xy*zx - xx*zy) * dW;
|
||||
temp.zz = (xx*yy - xy*yx) * dW;
|
||||
temp.zw = zw;
|
||||
|
||||
temp.wx = (yy*(zx*wz - zz*wx) + yz*(zy*wx - zx*wy) - yx*(zy*wz - zz*wy)) * dW;
|
||||
temp.wy = (xx*(zy*wz - zz*wy) + xy*(zz*wx - zx*wz) + xz*(zx*wy - zy*wx)) * dW;
|
||||
temp.wz = (xy*(yx*wz - yz*wx) + xz*(yy*wx - yx*wy) - xx*(yy*wz - yz*wy)) * dW;
|
||||
temp.ww = ww;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
void Matrix4x4::setViewLookAt(const Vec3 &vFrom, const Vec3 &vAt, const Vec3 &vWorldUp) {
|
||||
Vec3 vView = vFrom - vAt; // OpenGL, sigh...
|
||||
vView.normalize();
|
||||
float DotProduct = vWorldUp * vView;
|
||||
Vec3 vUp = vWorldUp - vView * DotProduct;
|
||||
float Length = vUp.length();
|
||||
Vec3 vView = vFrom - vAt; // OpenGL, sigh...
|
||||
vView.normalize();
|
||||
float DotProduct = vWorldUp * vView;
|
||||
Vec3 vUp = vWorldUp - vView * DotProduct;
|
||||
float Length = vUp.length();
|
||||
|
||||
if (1e-6f > Length) {
|
||||
if (1e-6f > Length) {
|
||||
// EMERGENCY
|
||||
vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y;
|
||||
// If we still have near-zero length, resort to a different axis.
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
{
|
||||
vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z;
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
return;
|
||||
}
|
||||
}
|
||||
vUp.normalize();
|
||||
Vec3 vRight = vUp % vView;
|
||||
empty();
|
||||
|
||||
xx = vRight.x; xy = vUp.x; xz=vView.x;
|
||||
yx = vRight.y; yy = vUp.y; yz=vView.y;
|
||||
zx = vRight.z; zy = vUp.z; zz=vView.z;
|
||||
|
||||
wx = -vFrom * vRight;
|
||||
wy = -vFrom * vUp;
|
||||
wz = -vFrom * vView;
|
||||
ww = 1.0f;
|
||||
vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y;
|
||||
// If we still have near-zero length, resort to a different axis.
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
{
|
||||
vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z;
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
return;
|
||||
}
|
||||
}
|
||||
vUp.normalize();
|
||||
Vec3 vRight = vUp % vView;
|
||||
empty();
|
||||
|
||||
xx = vRight.x; xy = vUp.x; xz=vView.x;
|
||||
yx = vRight.y; yy = vUp.y; yz=vView.y;
|
||||
zx = vRight.z; zy = vUp.z; zz=vView.z;
|
||||
|
||||
wx = -vFrom * vRight;
|
||||
wy = -vFrom * vUp;
|
||||
wz = -vFrom * vView;
|
||||
ww = 1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4::setViewLookAtD3D(const Vec3 &vFrom, const Vec3 &vAt, const Vec3 &vWorldUp) {
|
||||
Vec3 vView = vAt - vFrom;
|
||||
vView.normalize();
|
||||
float DotProduct = vWorldUp * vView;
|
||||
Vec3 vUp = vWorldUp - vView * DotProduct;
|
||||
float Length = vUp.length();
|
||||
Vec3 vView = vAt - vFrom;
|
||||
vView.normalize();
|
||||
float DotProduct = vWorldUp * vView;
|
||||
Vec3 vUp = vWorldUp - vView * DotProduct;
|
||||
float Length = vUp.length();
|
||||
|
||||
if (1e-6f > Length) {
|
||||
vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y;
|
||||
// If we still have near-zero length, resort to a different axis.
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
{
|
||||
vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z;
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
return;
|
||||
}
|
||||
}
|
||||
vUp.normalize();
|
||||
Vec3 vRight = vUp % vView;
|
||||
empty();
|
||||
|
||||
xx = vRight.x; xy = vUp.x; xz=vView.x;
|
||||
yx = vRight.y; yy = vUp.y; yz=vView.y;
|
||||
zx = vRight.z; zy = vUp.z; zz=vView.z;
|
||||
|
||||
wx = -vFrom * vRight;
|
||||
wy = -vFrom * vUp;
|
||||
wz = -vFrom * vView;
|
||||
ww = 1.0f;
|
||||
if (1e-6f > Length) {
|
||||
vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y;
|
||||
// If we still have near-zero length, resort to a different axis.
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
{
|
||||
vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z;
|
||||
Length = vUp.length();
|
||||
if (1e-6f > Length)
|
||||
return;
|
||||
}
|
||||
}
|
||||
vUp.normalize();
|
||||
Vec3 vRight = vUp % vView;
|
||||
empty();
|
||||
|
||||
xx = vRight.x; xy = vUp.x; xz=vView.x;
|
||||
yx = vRight.y; yy = vUp.y; yz=vView.y;
|
||||
zx = vRight.z; zy = vUp.z; zz=vView.z;
|
||||
|
||||
wx = -vFrom * vRight;
|
||||
wy = -vFrom * vUp;
|
||||
wz = -vFrom * vView;
|
||||
ww = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
void Matrix4x4::setViewFrame(const Vec3 &pos, const Vec3 &vRight, const Vec3 &vView, const Vec3 &vUp) {
|
||||
xx = vRight.x; xy = vUp.x; xz=vView.x; xw = 0.0f;
|
||||
yx = vRight.y; yy = vUp.y; yz=vView.y; yw = 0.0f;
|
||||
zx = vRight.z; zy = vUp.z; zz=vView.z; zw = 0.0f;
|
||||
|
||||
wx = -pos * vRight;
|
||||
wy = -pos * vUp;
|
||||
wz = -pos * vView;
|
||||
ww = 1.0f;
|
||||
xx = vRight.x; xy = vUp.x; xz=vView.x; xw = 0.0f;
|
||||
yx = vRight.y; yy = vUp.y; yz=vView.y; yw = 0.0f;
|
||||
zx = vRight.z; zy = vUp.z; zz=vView.z; zw = 0.0f;
|
||||
|
||||
wx = -pos * vRight;
|
||||
wy = -pos * vUp;
|
||||
wz = -pos * vView;
|
||||
ww = 1.0f;
|
||||
}
|
||||
|
||||
//YXZ euler angles
|
||||
void Matrix4x4::setRotation(float x,float y, float z)
|
||||
{
|
||||
setRotationY(y);
|
||||
Matrix4x4 temp;
|
||||
temp.setRotationX(x);
|
||||
*this *= temp;
|
||||
temp.setRotationZ(z);
|
||||
*this *= temp;
|
||||
setRotationY(y);
|
||||
Matrix4x4 temp;
|
||||
temp.setRotationX(x);
|
||||
*this *= temp;
|
||||
temp.setRotationZ(z);
|
||||
*this *= temp;
|
||||
}
|
||||
|
||||
void Matrix4x4::setProjection(float near, float far, float fov_horiz, float aspect) {
|
||||
// Now OpenGL style.
|
||||
empty();
|
||||
empty();
|
||||
|
||||
float xFac = tanf(fov_horiz * 3.14f/360);
|
||||
float yFac = xFac * aspect;
|
||||
@@ -208,17 +208,17 @@ void Matrix4x4::setProjection(float near, float far, float fov_horiz, float aspe
|
||||
}
|
||||
|
||||
void Matrix4x4::setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect) {
|
||||
empty();
|
||||
float Q, f;
|
||||
|
||||
f = fov_horiz*0.5f;
|
||||
Q = far_plane / (far_plane - near_plane);
|
||||
|
||||
xx = (float)(1.0f / tanf(f));;
|
||||
yy = (float)(1.0f / tanf(f*aspect));
|
||||
zz = Q;
|
||||
wz = -Q * near_plane;
|
||||
zw = 1.0f;
|
||||
empty();
|
||||
float Q, f;
|
||||
|
||||
f = fov_horiz*0.5f;
|
||||
Q = far_plane / (far_plane - near_plane);
|
||||
|
||||
xx = (float)(1.0f / tanf(f));;
|
||||
yy = (float)(1.0f / tanf(f*aspect));
|
||||
zz = Q;
|
||||
wz = -Q * near_plane;
|
||||
zw = 1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4::setOrtho(float left, float right, float bottom, float top, float near, float far) {
|
||||
@@ -233,43 +233,43 @@ void Matrix4x4::setOrtho(float left, float right, float bottom, float top, float
|
||||
|
||||
// This is a D3D style matrix.
|
||||
void Matrix4x4::setProjectionInf(const float near_plane, const float fov_horiz, const float aspect) {
|
||||
empty();
|
||||
float f = fov_horiz*0.5f;
|
||||
xx = 1.0f / tanf(f);
|
||||
yy = 1.0f / tanf(f*aspect);
|
||||
zz = 1;
|
||||
wz = -near_plane;
|
||||
zw = 1.0f;
|
||||
empty();
|
||||
float f = fov_horiz*0.5f;
|
||||
xx = 1.0f / tanf(f);
|
||||
yy = 1.0f / tanf(f*aspect);
|
||||
zz = 1;
|
||||
wz = -near_plane;
|
||||
zw = 1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4::setRotationAxisAngle(const Vec3 &axis, float angle) {
|
||||
Quaternion quat;
|
||||
quat.setRotation(axis, angle);
|
||||
quat.toMatrix(this);
|
||||
Quaternion quat;
|
||||
quat.setRotation(axis, angle);
|
||||
quat.toMatrix(this);
|
||||
}
|
||||
|
||||
// from a (Position, Rotation, Scale) vec3 quat vec3 tuple
|
||||
Matrix4x4 Matrix4x4::fromPRS(const Vec3 &positionv, const Quaternion &rotv, const Vec3 &scalev) {
|
||||
Matrix4x4 newM;
|
||||
newM.setIdentity();
|
||||
Matrix4x4 rot, scale;
|
||||
rotv.toMatrix(&rot);
|
||||
scale.setScaling(scalev);
|
||||
newM = rot * scale;
|
||||
newM.wx = positionv.x;
|
||||
Matrix4x4 newM;
|
||||
newM.setIdentity();
|
||||
Matrix4x4 rot, scale;
|
||||
rotv.toMatrix(&rot);
|
||||
scale.setScaling(scalev);
|
||||
newM = rot * scale;
|
||||
newM.wx = positionv.x;
|
||||
newM.wy = positionv.y;
|
||||
newM.wz = positionv.z;
|
||||
return newM;
|
||||
return newM;
|
||||
}
|
||||
#if _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
void Matrix4x4::toText(char *buffer, int len) const {
|
||||
snprintf(buffer, len, "%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n",
|
||||
xx,xy,xz,xw,
|
||||
yx,yy,yz,yw,
|
||||
zx,zy,zz,zw,
|
||||
wx,wy,wz,ww);
|
||||
snprintf(buffer, len, "%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n",
|
||||
xx,xy,xz,xw,
|
||||
yx,yy,yz,yw,
|
||||
zx,zy,zz,zw,
|
||||
wx,wy,wz,ww);
|
||||
buffer[len - 1] = '\0';
|
||||
}
|
||||
|
||||
|
||||
+106
-106
@@ -6,17 +6,17 @@
|
||||
class Quaternion;
|
||||
|
||||
class Matrix4x4 {
|
||||
public:
|
||||
float xx, xy, xz, xw;
|
||||
float yx, yy, yz, yw;
|
||||
float zx, zy, zz, zw;
|
||||
float wx, wy, wz, ww;
|
||||
public:
|
||||
float xx, xy, xz, xw;
|
||||
float yx, yy, yz, yw;
|
||||
float zx, zy, zz, zw;
|
||||
float wx, wy, wz, ww;
|
||||
|
||||
const Vec3 right() const {return Vec3(xx, xy, xz);}
|
||||
const Vec3 up() const {return Vec3(yx, yy, yz);}
|
||||
const Vec3 front() const {return Vec3(zx, zy, zz);}
|
||||
const Vec3 move() const {return Vec3(wx, wy, wz);}
|
||||
|
||||
const Vec3 right() const {return Vec3(xx, xy, xz);}
|
||||
const Vec3 up() const {return Vec3(yx, yy, yz);}
|
||||
const Vec3 front() const {return Vec3(zx, zy, zz);}
|
||||
const Vec3 move() const {return Vec3(wx, wy, wz);}
|
||||
|
||||
void setRight(const Vec3 &v) {
|
||||
xx = v.x; xy = v.y; xz = v.z;
|
||||
}
|
||||
@@ -31,110 +31,110 @@ class Matrix4x4 {
|
||||
}
|
||||
|
||||
|
||||
const float &operator[](int i) const {
|
||||
return *(((const float *)this) + i);
|
||||
}
|
||||
float &operator[](int i) {
|
||||
return *(((float *)this) + i);
|
||||
}
|
||||
Matrix4x4 operator * (const Matrix4x4 &other) const ;
|
||||
void operator *= (const Matrix4x4 &other) {
|
||||
*this = *this * other;
|
||||
}
|
||||
const float &operator[](int i) const {
|
||||
return *(((const float *)this) + i);
|
||||
}
|
||||
float &operator[](int i) {
|
||||
return *(((float *)this) + i);
|
||||
}
|
||||
Matrix4x4 operator * (const Matrix4x4 &other) const ;
|
||||
void operator *= (const Matrix4x4 &other) {
|
||||
*this = *this * other;
|
||||
}
|
||||
const float *getReadPtr() const {
|
||||
return (const float *)this;
|
||||
}
|
||||
void empty() {
|
||||
memset(this, 0, 16 * sizeof(float));
|
||||
}
|
||||
void setScaling(const float f) {
|
||||
empty();
|
||||
xx=yy=zz=f; ww=1.0f;
|
||||
}
|
||||
void setScaling(const Vec3 f) {
|
||||
empty();
|
||||
xx=f.x;
|
||||
yy=f.y;
|
||||
zz=f.z;
|
||||
ww=1.0f;
|
||||
}
|
||||
|
||||
void setIdentity() {
|
||||
setScaling(1.0f);
|
||||
}
|
||||
void setTranslation(const Vec3 &trans) {
|
||||
setIdentity();
|
||||
wx = trans.x;
|
||||
void empty() {
|
||||
memset(this, 0, 16 * sizeof(float));
|
||||
}
|
||||
void setScaling(const float f) {
|
||||
empty();
|
||||
xx=yy=zz=f; ww=1.0f;
|
||||
}
|
||||
void setScaling(const Vec3 f) {
|
||||
empty();
|
||||
xx=f.x;
|
||||
yy=f.y;
|
||||
zz=f.z;
|
||||
ww=1.0f;
|
||||
}
|
||||
|
||||
void setIdentity() {
|
||||
setScaling(1.0f);
|
||||
}
|
||||
void setTranslation(const Vec3 &trans) {
|
||||
setIdentity();
|
||||
wx = trans.x;
|
||||
wy = trans.y;
|
||||
wz = trans.z;
|
||||
}
|
||||
Matrix4x4 inverse() const;
|
||||
Matrix4x4 simpleInverse() const;
|
||||
Matrix4x4 transpose() const;
|
||||
|
||||
void setRotationX(const float a) {
|
||||
empty();
|
||||
float c=cosf(a);
|
||||
float s=sinf(a);
|
||||
xx = 1.0f;
|
||||
yy = c; yz = s;
|
||||
zy = -s; zz = c;
|
||||
ww = 1.0f;
|
||||
}
|
||||
void setRotationY(const float a) {
|
||||
empty();
|
||||
float c=cosf(a);
|
||||
float s=sinf(a);
|
||||
xx = c; xz = -s;
|
||||
yy = 1.0f;
|
||||
zx = s; zz = c ;
|
||||
ww = 1.0f;
|
||||
}
|
||||
void setRotationZ(const float a) {
|
||||
empty();
|
||||
float c=cosf(a);
|
||||
float s=sinf(a);
|
||||
xx = c; xy = s;
|
||||
yx = -s; yy = c;
|
||||
zz = 1.0f;
|
||||
ww = 1.0f;
|
||||
}
|
||||
void setRotationAxisAngle(const Vec3 &axis, float angle);
|
||||
|
||||
|
||||
void setRotation(float x,float y, float z);
|
||||
void setProjection(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f);
|
||||
void setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f);
|
||||
void setProjectionInf(float near_plane, float fov_horiz, float aspect = 0.75f);
|
||||
void setOrtho(float left, float right, float bottom, float top, float near, float far);
|
||||
void setShadow(float Lx, float Ly, float Lz, float Lw) {
|
||||
float Pa=0;
|
||||
float Pb=1;
|
||||
float Pc=0;
|
||||
float Pd=0;
|
||||
//P = normalize(Plane);
|
||||
float d = (Pa*Lx + Pb*Ly + Pc*Lz + Pd*Lw);
|
||||
}
|
||||
Matrix4x4 inverse() const;
|
||||
Matrix4x4 simpleInverse() const;
|
||||
Matrix4x4 transpose() const;
|
||||
|
||||
xx=Pa * Lx + d; xy=Pa * Ly; xz=Pa * Lz; xw=Pa * Lw;
|
||||
yx=Pb * Lx; yy=Pb * Ly + d; yz=Pb * Lz; yw=Pb * Lw;
|
||||
zx=Pc * Lx; zy=Pc * Ly; zz=Pc * Lz + d; zw=Pc * Lw;
|
||||
wx=Pd * Lx; wy=Pd * Ly; wz=Pd * Lz; ww=Pd * Lw + d;
|
||||
}
|
||||
void setRotationX(const float a) {
|
||||
empty();
|
||||
float c=cosf(a);
|
||||
float s=sinf(a);
|
||||
xx = 1.0f;
|
||||
yy = c; yz = s;
|
||||
zy = -s; zz = c;
|
||||
ww = 1.0f;
|
||||
}
|
||||
void setRotationY(const float a) {
|
||||
empty();
|
||||
float c=cosf(a);
|
||||
float s=sinf(a);
|
||||
xx = c; xz = -s;
|
||||
yy = 1.0f;
|
||||
zx = s; zz = c ;
|
||||
ww = 1.0f;
|
||||
}
|
||||
void setRotationZ(const float a) {
|
||||
empty();
|
||||
float c=cosf(a);
|
||||
float s=sinf(a);
|
||||
xx = c; xy = s;
|
||||
yx = -s; yy = c;
|
||||
zz = 1.0f;
|
||||
ww = 1.0f;
|
||||
}
|
||||
void setRotationAxisAngle(const Vec3 &axis, float angle);
|
||||
|
||||
void setViewLookAt(const Vec3 &from, const Vec3 &at, const Vec3 &worldup);
|
||||
void setViewLookAtD3D(const Vec3 &from, const Vec3 &at, const Vec3 &worldup);
|
||||
void setViewFrame(const Vec3 &pos, const Vec3 &right, const Vec3 &forward, const Vec3 &up);
|
||||
void stabilizeOrtho() {
|
||||
/*
|
||||
front().normalize();
|
||||
right().normalize();
|
||||
up() = front() % right();
|
||||
right() = up() % front();
|
||||
*/
|
||||
}
|
||||
void toText(char *buffer, int len) const;
|
||||
|
||||
void setRotation(float x,float y, float z);
|
||||
void setProjection(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f);
|
||||
void setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f);
|
||||
void setProjectionInf(float near_plane, float fov_horiz, float aspect = 0.75f);
|
||||
void setOrtho(float left, float right, float bottom, float top, float near, float far);
|
||||
void setShadow(float Lx, float Ly, float Lz, float Lw) {
|
||||
float Pa=0;
|
||||
float Pb=1;
|
||||
float Pc=0;
|
||||
float Pd=0;
|
||||
//P = normalize(Plane);
|
||||
float d = (Pa*Lx + Pb*Ly + Pc*Lz + Pd*Lw);
|
||||
|
||||
xx=Pa * Lx + d; xy=Pa * Ly; xz=Pa * Lz; xw=Pa * Lw;
|
||||
yx=Pb * Lx; yy=Pb * Ly + d; yz=Pb * Lz; yw=Pb * Lw;
|
||||
zx=Pc * Lx; zy=Pc * Ly; zz=Pc * Lz + d; zw=Pc * Lw;
|
||||
wx=Pd * Lx; wy=Pd * Ly; wz=Pd * Lz; ww=Pd * Lw + d;
|
||||
}
|
||||
|
||||
void setViewLookAt(const Vec3 &from, const Vec3 &at, const Vec3 &worldup);
|
||||
void setViewLookAtD3D(const Vec3 &from, const Vec3 &at, const Vec3 &worldup);
|
||||
void setViewFrame(const Vec3 &pos, const Vec3 &right, const Vec3 &forward, const Vec3 &up);
|
||||
void stabilizeOrtho() {
|
||||
/*
|
||||
front().normalize();
|
||||
right().normalize();
|
||||
up() = front() % right();
|
||||
right() = up() % front();
|
||||
*/
|
||||
}
|
||||
void toText(char *buffer, int len) const;
|
||||
void print() const;
|
||||
static Matrix4x4 fromPRS(const Vec3 &position, const Quaternion &normal, const Vec3 &scale);
|
||||
static Matrix4x4 fromPRS(const Vec3 &position, const Quaternion &normal, const Vec3 &scale);
|
||||
};
|
||||
|
||||
#endif // _MATH_LIN_MATRIX4X4_H
|
||||
|
||||
+95
-95
@@ -2,124 +2,124 @@
|
||||
#include "math/lin/matrix4x4.h"
|
||||
|
||||
void Quaternion::toMatrix(Matrix4x4 *out) const {
|
||||
Matrix4x4 temp;
|
||||
temp.setIdentity();
|
||||
float ww, xx, yy, zz, wx, wy, wz, xy, xz, yz;
|
||||
ww = w*w; xx = x*x; yy = y*y; zz = z*z;
|
||||
wx = w*x*2; wy = w*y*2; wz = w*z*2;
|
||||
xy = x*y*2; xz = x*z*2; yz = y*z*2;
|
||||
|
||||
temp.xx = ww + xx - yy - zz;
|
||||
temp.xy = xy + wz;
|
||||
temp.xz = xz - wy;
|
||||
|
||||
temp.yx = xy - wz;
|
||||
temp.yy = ww - xx + yy - zz;
|
||||
temp.yz = yz + wx;
|
||||
|
||||
temp.zx = xz + wy;
|
||||
temp.zy = yz - wx;
|
||||
temp.zz = ww - xx - yy + zz;
|
||||
|
||||
*out = temp;
|
||||
Matrix4x4 temp;
|
||||
temp.setIdentity();
|
||||
float ww, xx, yy, zz, wx, wy, wz, xy, xz, yz;
|
||||
ww = w*w; xx = x*x; yy = y*y; zz = z*z;
|
||||
wx = w*x*2; wy = w*y*2; wz = w*z*2;
|
||||
xy = x*y*2; xz = x*z*2; yz = y*z*2;
|
||||
|
||||
temp.xx = ww + xx - yy - zz;
|
||||
temp.xy = xy + wz;
|
||||
temp.xz = xz - wy;
|
||||
|
||||
temp.yx = xy - wz;
|
||||
temp.yy = ww - xx + yy - zz;
|
||||
temp.yz = yz + wx;
|
||||
|
||||
temp.zx = xz + wy;
|
||||
temp.zy = yz - wx;
|
||||
temp.zz = ww - xx - yy + zz;
|
||||
|
||||
*out = temp;
|
||||
}
|
||||
|
||||
Quaternion Quaternion::fromMatrix(Matrix4x4 &m)
|
||||
{
|
||||
// Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
|
||||
// article "Quaternion Calculus and Fast Animation".
|
||||
Quaternion q(0,0,0,1);
|
||||
// Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
|
||||
// article "Quaternion Calculus and Fast Animation".
|
||||
Quaternion q(0,0,0,1);
|
||||
/*
|
||||
float fTrace = m[0][0] + m[1][1] + m[2][2];
|
||||
float fRoot;
|
||||
float fTrace = m[0][0] + m[1][1] + m[2][2];
|
||||
float fRoot;
|
||||
|
||||
if( fTrace > 0.0 )
|
||||
{
|
||||
fRoot = sqrtf( fTrace + 1.0f );
|
||||
if( fTrace > 0.0 )
|
||||
{
|
||||
fRoot = sqrtf( fTrace + 1.0f );
|
||||
|
||||
q.w = 0.5f * fRoot;
|
||||
q.w = 0.5f * fRoot;
|
||||
|
||||
fRoot = 0.5f / fRoot;
|
||||
fRoot = 0.5f / fRoot;
|
||||
|
||||
q.x = ( m[2][1] - m[1][2] ) * fRoot;
|
||||
q.y = ( m[0][2] - m[2][0] ) * fRoot;
|
||||
q.z = ( m[1][0] - m[0][1] ) * fRoot;
|
||||
}
|
||||
else
|
||||
{
|
||||
int iNext[3] = { 1, 2, 0 };
|
||||
q.x = ( m[2][1] - m[1][2] ) * fRoot;
|
||||
q.y = ( m[0][2] - m[2][0] ) * fRoot;
|
||||
q.z = ( m[1][0] - m[0][1] ) * fRoot;
|
||||
}
|
||||
else
|
||||
{
|
||||
int iNext[3] = { 1, 2, 0 };
|
||||
|
||||
int i = 0;
|
||||
if( m[1][1] > m[0][0] )
|
||||
i = 1;
|
||||
int i = 0;
|
||||
if( m[1][1] > m[0][0] )
|
||||
i = 1;
|
||||
|
||||
if( m[2][2] > m[i][i] )
|
||||
i = 2;
|
||||
if( m[2][2] > m[i][i] )
|
||||
i = 2;
|
||||
|
||||
int j = iNext[i];
|
||||
int k = iNext[j];
|
||||
int j = iNext[i];
|
||||
int k = iNext[j];
|
||||
|
||||
fRoot = sqrtf( m[i][i] - m[j][j] - m[k][k] + 1.0f );
|
||||
fRoot = sqrtf( m[i][i] - m[j][j] - m[k][k] + 1.0f );
|
||||
|
||||
float *apfQuat = &q.x;
|
||||
float *apfQuat = &q.x;
|
||||
|
||||
apfQuat[i] = 0.5f * fRoot;
|
||||
apfQuat[i] = 0.5f * fRoot;
|
||||
|
||||
fRoot = 0.5f / fRoot;
|
||||
fRoot = 0.5f / fRoot;
|
||||
|
||||
q.w = ( m[k][j] - m[j][k] ) * fRoot;
|
||||
q.w = ( m[k][j] - m[j][k] ) * fRoot;
|
||||
|
||||
apfQuat[j] = ( m[j][i] + m[i][j] ) * fRoot;
|
||||
apfQuat[k] = ( m[k][i] + m[i][k] ) * fRoot;
|
||||
}
|
||||
q.normalize(); */
|
||||
return q;
|
||||
apfQuat[j] = ( m[j][i] + m[i][j] ) * fRoot;
|
||||
apfQuat[k] = ( m[k][i] + m[i][k] ) * fRoot;
|
||||
}
|
||||
q.normalize(); */
|
||||
return q;
|
||||
};
|
||||
|
||||
// TODO: Allegedly, lerp + normalize can achieve almost as good results.
|
||||
Quaternion Quaternion::slerp(const Quaternion &to, const float a) const {
|
||||
Quaternion to2;
|
||||
float angle, cos_angle, scale_from, scale_to, sin_angle;
|
||||
|
||||
cos_angle = (x * to.x) + (y * to.y) + (z * to.z) + (w * to.w); //4D dot product
|
||||
|
||||
if (cos_angle < 0.0f)
|
||||
{
|
||||
cos_angle = -cos_angle;
|
||||
to2.w = -to.w; to2.x = -to.x; to2.y = -to.y; to2.z = -to.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
to2 = to;
|
||||
}
|
||||
|
||||
if ((1.0f - fabsf(cos_angle)) > 0.00001f)
|
||||
{
|
||||
/* spherical linear interpolation (SLERP) */
|
||||
angle = acosf(cos_angle);
|
||||
sin_angle = sinf(angle);
|
||||
scale_from = sinf((1.0f - a) * angle) / sin_angle;
|
||||
scale_to = sinf(a * angle) / sin_angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* to prevent divide-by-zero, resort to linear interpolation */
|
||||
// This is okay in 99% of cases anyway, maybe should be the default?
|
||||
scale_from = 1.0f - a;
|
||||
scale_to = a;
|
||||
}
|
||||
|
||||
return Quaternion(
|
||||
scale_from*x + scale_to*to2.x,
|
||||
scale_from*y + scale_to*to2.y,
|
||||
scale_from*z + scale_to*to2.z,
|
||||
scale_from*w + scale_to*to2.w
|
||||
);
|
||||
Quaternion to2;
|
||||
float angle, cos_angle, scale_from, scale_to, sin_angle;
|
||||
|
||||
cos_angle = (x * to.x) + (y * to.y) + (z * to.z) + (w * to.w); //4D dot product
|
||||
|
||||
if (cos_angle < 0.0f)
|
||||
{
|
||||
cos_angle = -cos_angle;
|
||||
to2.w = -to.w; to2.x = -to.x; to2.y = -to.y; to2.z = -to.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
to2 = to;
|
||||
}
|
||||
|
||||
if ((1.0f - fabsf(cos_angle)) > 0.00001f)
|
||||
{
|
||||
/* spherical linear interpolation (SLERP) */
|
||||
angle = acosf(cos_angle);
|
||||
sin_angle = sinf(angle);
|
||||
scale_from = sinf((1.0f - a) * angle) / sin_angle;
|
||||
scale_to = sinf(a * angle) / sin_angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* to prevent divide-by-zero, resort to linear interpolation */
|
||||
// This is okay in 99% of cases anyway, maybe should be the default?
|
||||
scale_from = 1.0f - a;
|
||||
scale_to = a;
|
||||
}
|
||||
|
||||
return Quaternion(
|
||||
scale_from*x + scale_to*to2.x,
|
||||
scale_from*y + scale_to*to2.y,
|
||||
scale_from*z + scale_to*to2.z,
|
||||
scale_from*w + scale_to*to2.w
|
||||
);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::multiply(const Quaternion &q) const {
|
||||
return Quaternion((w * q.x) + (x * q.w) + (y * q.z) - (z * q.y),
|
||||
(w * q.y) + (y * q.w) + (z * q.x) - (x * q.z),
|
||||
(w * q.z) + (z * q.w) + (x * q.y) - (y * q.x),
|
||||
(w * q.w) - (x * q.x) - (y * q.y) - (z * q.z));
|
||||
return Quaternion((w * q.x) + (x * q.w) + (y * q.z) - (z * q.y),
|
||||
(w * q.y) + (y * q.w) + (z * q.x) - (x * q.z),
|
||||
(w * q.z) + (z * q.w) + (x * q.y) - (y * q.x),
|
||||
(w * q.w) - (x * q.x) - (y * q.y) - (z * q.z));
|
||||
}
|
||||
+78
-78
@@ -8,85 +8,85 @@ class Matrix4x4;
|
||||
class Quaternion
|
||||
{
|
||||
public:
|
||||
float x,y,z,w;
|
||||
|
||||
Quaternion() { }
|
||||
Quaternion(const float _x, const float _y, const float _z, const float _w) {
|
||||
x=_x; y=_y; z=_z; w=_w;
|
||||
}
|
||||
void setIdentity()
|
||||
{
|
||||
x=y=z=0; w=1.0f;
|
||||
}
|
||||
void setXRotation(const float r) { w = cosf(r / 2); x = sinf(r / 2); y = z = 0; }
|
||||
void setYRotation(const float r) { w = cosf(r / 2); y = sinf(r / 2); x = z = 0; }
|
||||
void setZRotation(const float r) { w = cosf(r / 2); z = sinf(r / 2); x = y = 0; }
|
||||
void toMatrix(Matrix4x4 *out) const;
|
||||
static Quaternion fromMatrix(Matrix4x4 &m);
|
||||
float x,y,z,w;
|
||||
|
||||
Quaternion operator *(Quaternion &q) const
|
||||
{
|
||||
return Quaternion(
|
||||
(w * q.w) - (x * q.x) - (y * q.y) - (z * q.z),
|
||||
(w * q.x) + (x * q.w) + (y * q.z) - (z * q.y),
|
||||
(w * q.y) + (y * q.w) + (z * q.x) - (x * q.z),
|
||||
(w * q.z) + (z * q.w) + (x * q.y) - (y * q.x)
|
||||
);
|
||||
}
|
||||
Quaternion operator -()
|
||||
{
|
||||
return Quaternion(-x,-y,-z,-w);
|
||||
}
|
||||
void setRotation(Vec3 axis, float angle)
|
||||
{
|
||||
axis /= axis.length();
|
||||
angle *= .5f;
|
||||
float sine = sinf(angle);
|
||||
w = cosf(angle);
|
||||
x = sine * axis.x;
|
||||
y = sine * axis.y;
|
||||
z = sine * axis.z;
|
||||
}
|
||||
void toAxisAngle(Vec3 &v, float &angle)
|
||||
{
|
||||
normalize();
|
||||
if (w==1.0f && x==0.0f && y==0.0f && z==0.0f)
|
||||
{
|
||||
v = Vec3(0,1,0);
|
||||
angle = 0.0f;
|
||||
return;
|
||||
}
|
||||
float cos_a = w;
|
||||
angle = acosf(cos_a) * 2;
|
||||
float sin_a = sqrtf( 1.0f - cos_a * cos_a );
|
||||
if (fabsf(sin_a) < 0.00005f) sin_a = 1;
|
||||
float inv_sin_a=1.0f/sin_a;
|
||||
v.x = x * inv_sin_a;
|
||||
v.y = y * inv_sin_a;
|
||||
v.z = z * inv_sin_a;
|
||||
}
|
||||
enum {
|
||||
QUAT_SHORT,
|
||||
QUAT_LONG,
|
||||
QUAT_CW,
|
||||
QUAT_CCW
|
||||
};
|
||||
Quaternion slerp(const Quaternion &to, const float a) const;
|
||||
Quaternion multiply(const Quaternion &q) const;
|
||||
float &operator [] (int i) {
|
||||
return *((&x) + i);
|
||||
}
|
||||
const float operator [] (int i) const {
|
||||
return *((&x) + i);
|
||||
}
|
||||
//not sure about this, maybe mag is supposed to sqrt
|
||||
float magnitude() const {
|
||||
return x*x + y*y + z*z + w*w;
|
||||
}
|
||||
void normalize() {
|
||||
float f = 1.0f/sqrtf(magnitude());
|
||||
x*=f; y*=f; z*=f; w*=f;
|
||||
}
|
||||
Quaternion() { }
|
||||
Quaternion(const float _x, const float _y, const float _z, const float _w) {
|
||||
x=_x; y=_y; z=_z; w=_w;
|
||||
}
|
||||
void setIdentity()
|
||||
{
|
||||
x=y=z=0; w=1.0f;
|
||||
}
|
||||
void setXRotation(const float r) { w = cosf(r / 2); x = sinf(r / 2); y = z = 0; }
|
||||
void setYRotation(const float r) { w = cosf(r / 2); y = sinf(r / 2); x = z = 0; }
|
||||
void setZRotation(const float r) { w = cosf(r / 2); z = sinf(r / 2); x = y = 0; }
|
||||
void toMatrix(Matrix4x4 *out) const;
|
||||
static Quaternion fromMatrix(Matrix4x4 &m);
|
||||
|
||||
Quaternion operator *(Quaternion &q) const
|
||||
{
|
||||
return Quaternion(
|
||||
(w * q.w) - (x * q.x) - (y * q.y) - (z * q.z),
|
||||
(w * q.x) + (x * q.w) + (y * q.z) - (z * q.y),
|
||||
(w * q.y) + (y * q.w) + (z * q.x) - (x * q.z),
|
||||
(w * q.z) + (z * q.w) + (x * q.y) - (y * q.x)
|
||||
);
|
||||
}
|
||||
Quaternion operator -()
|
||||
{
|
||||
return Quaternion(-x,-y,-z,-w);
|
||||
}
|
||||
void setRotation(Vec3 axis, float angle)
|
||||
{
|
||||
axis /= axis.length();
|
||||
angle *= .5f;
|
||||
float sine = sinf(angle);
|
||||
w = cosf(angle);
|
||||
x = sine * axis.x;
|
||||
y = sine * axis.y;
|
||||
z = sine * axis.z;
|
||||
}
|
||||
void toAxisAngle(Vec3 &v, float &angle)
|
||||
{
|
||||
normalize();
|
||||
if (w==1.0f && x==0.0f && y==0.0f && z==0.0f)
|
||||
{
|
||||
v = Vec3(0,1,0);
|
||||
angle = 0.0f;
|
||||
return;
|
||||
}
|
||||
float cos_a = w;
|
||||
angle = acosf(cos_a) * 2;
|
||||
float sin_a = sqrtf( 1.0f - cos_a * cos_a );
|
||||
if (fabsf(sin_a) < 0.00005f) sin_a = 1;
|
||||
float inv_sin_a=1.0f/sin_a;
|
||||
v.x = x * inv_sin_a;
|
||||
v.y = y * inv_sin_a;
|
||||
v.z = z * inv_sin_a;
|
||||
}
|
||||
enum {
|
||||
QUAT_SHORT,
|
||||
QUAT_LONG,
|
||||
QUAT_CW,
|
||||
QUAT_CCW
|
||||
};
|
||||
Quaternion slerp(const Quaternion &to, const float a) const;
|
||||
Quaternion multiply(const Quaternion &q) const;
|
||||
float &operator [] (int i) {
|
||||
return *((&x) + i);
|
||||
}
|
||||
const float operator [] (int i) const {
|
||||
return *((&x) + i);
|
||||
}
|
||||
//not sure about this, maybe mag is supposed to sqrt
|
||||
float magnitude() const {
|
||||
return x*x + y*y + z*z + w*w;
|
||||
}
|
||||
void normalize() {
|
||||
float f = 1.0f/sqrtf(magnitude());
|
||||
x*=f; y*=f; z*=f; w*=f;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _MATH_LIN_QUAT_H
|
||||
+14
-14
@@ -4,25 +4,25 @@
|
||||
#include "math/lin/matrix4x4.h"
|
||||
|
||||
Vec3 Vec3::operator *(const Matrix4x4 &m) const {
|
||||
return Vec3(x*m.xx + y*m.yx + z*m.zx + m.wx,
|
||||
x*m.xy + y*m.yy + z*m.zy + m.wy,
|
||||
x*m.xz + y*m.yz + z*m.zz + m.wz);
|
||||
return Vec3(x*m.xx + y*m.yx + z*m.zx + m.wx,
|
||||
x*m.xy + y*m.yy + z*m.zy + m.wy,
|
||||
x*m.xz + y*m.yz + z*m.zz + m.wz);
|
||||
}
|
||||
Vec4 Vec3::multiply4D(const Matrix4x4 &m) const {
|
||||
return Vec4(x*m.xx + y*m.yx + z*m.zx + m.wx,
|
||||
x*m.xy + y*m.yy + z*m.zy + m.wy,
|
||||
x*m.xz + y*m.yz + z*m.zz + m.wz,
|
||||
x*m.xw + y*m.yw + z*m.zw + m.ww);
|
||||
return Vec4(x*m.xx + y*m.yx + z*m.zx + m.wx,
|
||||
x*m.xy + y*m.yy + z*m.zy + m.wy,
|
||||
x*m.xz + y*m.yz + z*m.zz + m.wz,
|
||||
x*m.xw + y*m.yw + z*m.zw + m.ww);
|
||||
}
|
||||
Vec4 Vec4::multiply4D(Matrix4x4 &m) const {
|
||||
return Vec4(x*m.xx + y*m.yx + z*m.zx + w*m.wx,
|
||||
x*m.xy + y*m.yy + z*m.zy + w*m.wy,
|
||||
x*m.xz + y*m.yz + z*m.zz + w*m.wz,
|
||||
x*m.xw + y*m.yw + z*m.zw + w*m.ww);
|
||||
return Vec4(x*m.xx + y*m.yx + z*m.zx + w*m.wx,
|
||||
x*m.xy + y*m.yy + z*m.zy + w*m.wy,
|
||||
x*m.xz + y*m.yz + z*m.zz + w*m.wz,
|
||||
x*m.xw + y*m.yw + z*m.zw + w*m.ww);
|
||||
}
|
||||
|
||||
Vec3 Vec3::rotatedBy(const Matrix4x4 &m) const {
|
||||
return Vec3(x*m.xx + y*m.yx + z*m.zx,
|
||||
x*m.xy + y*m.yy + z*m.zy,
|
||||
x*m.xz + y*m.yz + z*m.zz);
|
||||
return Vec3(x*m.xx + y*m.yx + z*m.zx,
|
||||
x*m.xy + y*m.yy + z*m.zy,
|
||||
x*m.xz + y*m.yz + z*m.zz);
|
||||
}
|
||||
+102
-102
@@ -18,112 +18,112 @@ class Matrix4x4;
|
||||
// Hm, doesn't belong in this file.
|
||||
class Vec4 {
|
||||
public:
|
||||
float x,y,z,w;
|
||||
Vec4(){}
|
||||
Vec4(float a, float b, float c, float d) {x=a;y=b;z=c;w=d;}
|
||||
Vec4 multiply4D(Matrix4x4 &m) const;
|
||||
float x,y,z,w;
|
||||
Vec4(){}
|
||||
Vec4(float a, float b, float c, float d) {x=a;y=b;z=c;w=d;}
|
||||
Vec4 multiply4D(Matrix4x4 &m) const;
|
||||
};
|
||||
|
||||
class Vec3 {
|
||||
public:
|
||||
float x,y,z;
|
||||
|
||||
Vec3() { }
|
||||
explicit Vec3(float f) {x=y=z=f;}
|
||||
float x,y,z;
|
||||
|
||||
Vec3(const float _x, const float _y, const float _z) {
|
||||
x=_x; y=_y; z=_z;
|
||||
}
|
||||
void Set(float _x, float _y, float _z) {
|
||||
x=_x; y=_y; z=_z;
|
||||
}
|
||||
Vec3 operator + (const Vec3 &other) const {
|
||||
return Vec3(x+other.x, y+other.y, z+other.z);
|
||||
}
|
||||
void operator += (const Vec3 &other) {
|
||||
x+=other.x; y+=other.y; z+=other.z;
|
||||
}
|
||||
Vec3 operator -(const Vec3 &v) const {
|
||||
return Vec3(x-v.x,y-v.y,z-v.z);
|
||||
}
|
||||
void operator -= (const Vec3 &other)
|
||||
{
|
||||
x-=other.x; y-=other.y; z-=other.z;
|
||||
}
|
||||
Vec3 operator -() const {
|
||||
return Vec3(-x,-y,-z);
|
||||
}
|
||||
Vec3() { }
|
||||
explicit Vec3(float f) {x=y=z=f;}
|
||||
|
||||
Vec3 operator * (const float f) const {
|
||||
return Vec3(x*f,y*f,z*f);
|
||||
}
|
||||
Vec3 operator / (const float f) const {
|
||||
float invf = (1.0f/f);
|
||||
return Vec3(x*invf,y*invf,z*invf);
|
||||
}
|
||||
void operator /= (const float f)
|
||||
{
|
||||
*this = *this / f;
|
||||
}
|
||||
float operator * (const Vec3 &other) const {
|
||||
return x*other.x + y*other.y + z*other.z;
|
||||
}
|
||||
void operator *= (const float f) {
|
||||
*this = *this * f;
|
||||
}
|
||||
void scaleBy(const Vec3 &other) {
|
||||
x *= other.x; y *= other.y; z *= other.z;
|
||||
}
|
||||
Vec3 scaledBy(const Vec3 &other) const {
|
||||
return Vec3(x*other.x, y*other.y, z*other.z);
|
||||
}
|
||||
Vec3 scaledByInv(const Vec3 &other) const {
|
||||
return Vec3(x/other.x, y/other.y, z/other.z);
|
||||
}
|
||||
Vec3 operator *(const Matrix4x4 &m) const;
|
||||
void operator *=(const Matrix4x4 &m) {
|
||||
*this = *this * m;
|
||||
}
|
||||
Vec4 multiply4D(const Matrix4x4 &m) const;
|
||||
Vec3 rotatedBy(const Matrix4x4 &m) const;
|
||||
Vec3 operator %(const Vec3 &v) const {
|
||||
return Vec3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x);
|
||||
}
|
||||
float length2() const {
|
||||
return x*x + y*y + z*z;
|
||||
}
|
||||
float length() const {
|
||||
return sqrtf(length2());
|
||||
}
|
||||
void setLength(const float l) {
|
||||
(*this) *= l/length();
|
||||
}
|
||||
Vec3 withLength(const float l) const {
|
||||
return (*this) * l / length();
|
||||
}
|
||||
float distance2To(const Vec3 &other) const {
|
||||
return Vec3(other-(*this)).length2();
|
||||
}
|
||||
Vec3 normalized() const {
|
||||
return (*this) / length();
|
||||
}
|
||||
float normalize() { //returns the previous length, is often useful
|
||||
float len = length();
|
||||
(*this) = (*this)/len;
|
||||
return len;
|
||||
}
|
||||
bool operator == (const Vec3 &other) const {
|
||||
if (x==other.x && y==other.y && z==other.z)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
Vec3 lerp(const Vec3 &other, const float t) const {
|
||||
return (*this)*(1-t) + other*t;
|
||||
}
|
||||
void setZero() {
|
||||
memset((void *)this,0,sizeof(float)*3);
|
||||
}
|
||||
Vec3(const float _x, const float _y, const float _z) {
|
||||
x=_x; y=_y; z=_z;
|
||||
}
|
||||
void Set(float _x, float _y, float _z) {
|
||||
x=_x; y=_y; z=_z;
|
||||
}
|
||||
Vec3 operator + (const Vec3 &other) const {
|
||||
return Vec3(x+other.x, y+other.y, z+other.z);
|
||||
}
|
||||
void operator += (const Vec3 &other) {
|
||||
x+=other.x; y+=other.y; z+=other.z;
|
||||
}
|
||||
Vec3 operator -(const Vec3 &v) const {
|
||||
return Vec3(x-v.x,y-v.y,z-v.z);
|
||||
}
|
||||
void operator -= (const Vec3 &other)
|
||||
{
|
||||
x-=other.x; y-=other.y; z-=other.z;
|
||||
}
|
||||
Vec3 operator -() const {
|
||||
return Vec3(-x,-y,-z);
|
||||
}
|
||||
|
||||
Vec3 operator * (const float f) const {
|
||||
return Vec3(x*f,y*f,z*f);
|
||||
}
|
||||
Vec3 operator / (const float f) const {
|
||||
float invf = (1.0f/f);
|
||||
return Vec3(x*invf,y*invf,z*invf);
|
||||
}
|
||||
void operator /= (const float f)
|
||||
{
|
||||
*this = *this / f;
|
||||
}
|
||||
float operator * (const Vec3 &other) const {
|
||||
return x*other.x + y*other.y + z*other.z;
|
||||
}
|
||||
void operator *= (const float f) {
|
||||
*this = *this * f;
|
||||
}
|
||||
void scaleBy(const Vec3 &other) {
|
||||
x *= other.x; y *= other.y; z *= other.z;
|
||||
}
|
||||
Vec3 scaledBy(const Vec3 &other) const {
|
||||
return Vec3(x*other.x, y*other.y, z*other.z);
|
||||
}
|
||||
Vec3 scaledByInv(const Vec3 &other) const {
|
||||
return Vec3(x/other.x, y/other.y, z/other.z);
|
||||
}
|
||||
Vec3 operator *(const Matrix4x4 &m) const;
|
||||
void operator *=(const Matrix4x4 &m) {
|
||||
*this = *this * m;
|
||||
}
|
||||
Vec4 multiply4D(const Matrix4x4 &m) const;
|
||||
Vec3 rotatedBy(const Matrix4x4 &m) const;
|
||||
Vec3 operator %(const Vec3 &v) const {
|
||||
return Vec3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x);
|
||||
}
|
||||
float length2() const {
|
||||
return x*x + y*y + z*z;
|
||||
}
|
||||
float length() const {
|
||||
return sqrtf(length2());
|
||||
}
|
||||
void setLength(const float l) {
|
||||
(*this) *= l/length();
|
||||
}
|
||||
Vec3 withLength(const float l) const {
|
||||
return (*this) * l / length();
|
||||
}
|
||||
float distance2To(const Vec3 &other) const {
|
||||
return Vec3(other-(*this)).length2();
|
||||
}
|
||||
Vec3 normalized() const {
|
||||
return (*this) / length();
|
||||
}
|
||||
float normalize() { //returns the previous length, is often useful
|
||||
float len = length();
|
||||
(*this) = (*this)/len;
|
||||
return len;
|
||||
}
|
||||
bool operator == (const Vec3 &other) const {
|
||||
if (x==other.x && y==other.y && z==other.z)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
Vec3 lerp(const Vec3 &other, const float t) const {
|
||||
return (*this)*(1-t) + other*t;
|
||||
}
|
||||
void setZero() {
|
||||
memset((void *)this,0,sizeof(float)*3);
|
||||
}
|
||||
};
|
||||
|
||||
inline Vec3 operator * (const float f, const Vec3 &v) {return v * f;}
|
||||
@@ -144,8 +144,8 @@ inline float sqr(const Vec3 &v) {
|
||||
|
||||
class AABBox {
|
||||
public:
|
||||
Vec3 min;
|
||||
Vec3 max;
|
||||
Vec3 min;
|
||||
Vec3 max;
|
||||
};
|
||||
|
||||
#endif // _MATH_LIN_VEC3
|
||||
@@ -1,19 +0,0 @@
|
||||
#include "math/math_util.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
static unsigned int randSeed = 22222; // Change this for different random sequences.
|
||||
|
||||
void SetSeed(unsigned int seed) {
|
||||
randSeed = seed * 382792592;
|
||||
}
|
||||
|
||||
unsigned int GenerateRandomNumber() {
|
||||
randSeed = (randSeed * 196314165) + 907633515;
|
||||
randSeed ^= _rotl(randSeed, 13);
|
||||
return randSeed;
|
||||
}*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#include "math/math_util.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
static unsigned int randSeed = 22222; // Change this for different random sequences.
|
||||
|
||||
void SetSeed(unsigned int seed) {
|
||||
randSeed = seed * 382792592;
|
||||
}
|
||||
|
||||
unsigned int GenerateRandomNumber() {
|
||||
randSeed = (randSeed * 196314165) + 907633515;
|
||||
randSeed ^= _rotl(randSeed, 13);
|
||||
return randSeed;
|
||||
}*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
void EnableFZ()
|
||||
{
|
||||
int x;
|
||||
asm(
|
||||
"fmrx %[result],FPSCR \r\n"
|
||||
"orr %[result],%[result],#16777216 \r\n"
|
||||
"fmxr FPSCR,%[result]"
|
||||
:[result] "=r" (x) : :
|
||||
);
|
||||
//printf("ARM FPSCR: %08x\n",x);
|
||||
}
|
||||
|
||||
void DisableFZ( )
|
||||
{
|
||||
__asm__ volatile(
|
||||
"fmrx r0, fpscr\n"
|
||||
"bic r0, $(1 << 24)\n"
|
||||
"fmxr fpscr, r0" : : : "r0");
|
||||
}
|
||||
#else
|
||||
|
||||
void EnableFZ()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
void DisableFZ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+25
-37
@@ -8,16 +8,17 @@ typedef unsigned short float16;
|
||||
|
||||
// This ain't a 1.5.10 float16, it's a stupid hack format where we chop 16 bits off a float.
|
||||
// This choice is subject to change. Don't think I'm using this for anything at all now anyway.
|
||||
// DEPRECATED
|
||||
inline float16 FloatToFloat16(float x) {
|
||||
int ix;
|
||||
memcpy(&ix, &x, sizeof(float));
|
||||
return ix >> 16;
|
||||
int ix;
|
||||
memcpy(&ix, &x, sizeof(float));
|
||||
return ix >> 16;
|
||||
}
|
||||
|
||||
inline float Float16ToFloat(float16 ix) {
|
||||
float x;
|
||||
memcpy(&x, &ix, sizeof(float));
|
||||
return x;
|
||||
float x;
|
||||
memcpy(&x, &ix, sizeof(float));
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,62 +27,49 @@ inline float Float16ToFloat(float16 ix) {
|
||||
// The stuff in this file is from all over the web, esp. dspmusic.org. I think it's all public domain.
|
||||
// In any case, very little of it is used anywhere at the moment.
|
||||
|
||||
// PM modulated sine
|
||||
inline float sine(float t,float f,float ph,float fm) {
|
||||
return sinf((t*f+ph)*2*PI + 0.5f*PI*fm*(1 - sqrt(f*2)));
|
||||
}
|
||||
|
||||
//fb := feedback (0 to 1) (1 max saw)
|
||||
|
||||
inline float saw(float t,float f,float ph, float fm, float fb = 1.0f)
|
||||
{
|
||||
return sine(t,f,ph,fb*sine(t-1.0f,f,ph,fm));
|
||||
}
|
||||
|
||||
// pm := pulse mod (0 to 1) (1 max pulse)
|
||||
// pw := pulse width (0 to 1) (1 square)
|
||||
inline float pulse(float t,float f,float ph,float fm,float fb,float pm,float pw) {
|
||||
return saw(t,f,ph,fm,fb) - saw(t,f,ph+0.5f*pw,fm,fb) * pm;
|
||||
}
|
||||
|
||||
// Calculate pseudo-random 32 bit number based on linear congruential method.
|
||||
void SetSeed(unsigned int seed);
|
||||
unsigned int GenerateRandomNumber();
|
||||
inline float GenerateRandomFloat01() {
|
||||
return (float)((double)GenerateRandomNumber() / 0xFFFFFFFF);
|
||||
return (float)((double)GenerateRandomNumber() / 0xFFFFFFFF);
|
||||
}
|
||||
inline float GenerateRandomSignedFloat() {
|
||||
return (float)((double)GenerateRandomNumber() / 0x80000000) - 1.0f;
|
||||
return (float)((double)GenerateRandomNumber() / 0x80000000) - 1.0f;
|
||||
}
|
||||
|
||||
|
||||
inline float GaussRand()
|
||||
{
|
||||
float R1 = GenerateRandomFloat01();
|
||||
float R2 = GenerateRandomFloat01();
|
||||
float R1 = GenerateRandomFloat01();
|
||||
float R2 = GenerateRandomFloat01();
|
||||
|
||||
float X = sqrtf( -2.0f * logf(R1)) * cosf(2.0f * PI * R2);
|
||||
if (X > 4.0f) X = 4.0f;
|
||||
if (X < -4.0f) X = -4.0f;
|
||||
return X;
|
||||
float X = sqrtf(-2.0f * logf(R1)) * cosf(2.0f * PI * R2);
|
||||
if (X > 4.0f) X = 4.0f;
|
||||
if (X < -4.0f) X = -4.0f;
|
||||
return X;
|
||||
}
|
||||
|
||||
// Accuracy unknown
|
||||
inline double atan_fast(double x) {
|
||||
return (x / (1.0 + 0.28 * (x * x)));
|
||||
return (x / (1.0 + 0.28 * (x * x)));
|
||||
}
|
||||
|
||||
|
||||
// linear -> dB conversion
|
||||
inline float lin2dB(float lin) {
|
||||
const float LOG_2_DB = 8.6858896380650365530225783783321f; // 20 / ln( 10 )
|
||||
return log(lin) * LOG_2_DB;
|
||||
const float LOG_2_DB = 8.6858896380650365530225783783321f; // 20 / ln( 10 )
|
||||
return logf(lin) * LOG_2_DB;
|
||||
}
|
||||
|
||||
// dB -> linear conversion
|
||||
inline float dB2lin(float dB) {
|
||||
const float DB_2_LOG = 0.11512925464970228420089957273422f; // ln( 10 ) / 20
|
||||
return exp(dB * DB_2_LOG);
|
||||
const float DB_2_LOG = 0.11512925464970228420089957273422f; // ln( 10 ) / 20
|
||||
return expf(dB * DB_2_LOG);
|
||||
}
|
||||
|
||||
|
||||
// FPU control.
|
||||
void EnableFZ();
|
||||
void DisableFZ();
|
||||
|
||||
#endif
|
||||
+40
-41
@@ -13,53 +13,52 @@
|
||||
#include "midi/midi_input.h"
|
||||
|
||||
std::vector<std::string> MidiInGetDevices() {
|
||||
int numDevs = midiInGetNumDevs();
|
||||
std::vector<std::string> devices;
|
||||
for (int i = 0; i < numDevs; i++) {
|
||||
MIDIINCAPS caps;
|
||||
midiInGetDevCaps(i, &caps, sizeof(caps));
|
||||
devices.push_back(caps.szPname);
|
||||
}
|
||||
return devices;
|
||||
int numDevs = midiInGetNumDevs();
|
||||
std::vector<std::string> devices;
|
||||
for (int i = 0; i < numDevs; i++) {
|
||||
MIDIINCAPS caps;
|
||||
midiInGetDevCaps(i, &caps, sizeof(caps));
|
||||
devices.push_back(caps.szPname);
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
static void CALLBACK MidiCallback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance,
|
||||
DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
|
||||
MidiListener *listener = (MidiListener*)dwInstance;
|
||||
uint8_t cmd[3] = {0};
|
||||
static void CALLBACK MidiCallback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
|
||||
MidiListener *listener = (MidiListener*)dwInstance;
|
||||
uint8_t cmd[3] = {0};
|
||||
|
||||
switch (wMsg) {
|
||||
case MM_MIM_OPEN:
|
||||
ILOG("Got MIDI Open message");
|
||||
break;
|
||||
case MM_MIM_CLOSE:
|
||||
ILOG("Got MIDI Close message");
|
||||
break;
|
||||
case MM_MIM_DATA:
|
||||
cmd[0] = dwParam1 & 0xFF;
|
||||
cmd[1] = (dwParam1 >> 8) & 0xFF;
|
||||
cmd[2] = (dwParam1 >> 16) & 0xFF;
|
||||
// time = dwParam2 & 0xFFFF;
|
||||
ILOG("Got MIDI Data: %02x %02x %02x", cmd[0], cmd[1], cmd[2]);
|
||||
listener->midiEvent(cmd);
|
||||
break;
|
||||
default:
|
||||
WLOG("Got unexpected MIDI message: %08x", (uint32_t)wMsg);
|
||||
break;
|
||||
}
|
||||
switch (wMsg) {
|
||||
case MM_MIM_OPEN:
|
||||
ILOG("Got MIDI Open message");
|
||||
break;
|
||||
case MM_MIM_CLOSE:
|
||||
ILOG("Got MIDI Close message");
|
||||
break;
|
||||
case MM_MIM_DATA:
|
||||
cmd[0] = dwParam1 & 0xFF;
|
||||
cmd[1] = (dwParam1 >> 8) & 0xFF;
|
||||
cmd[2] = (dwParam1 >> 16) & 0xFF;
|
||||
// time = dwParam2 & 0xFFFF;
|
||||
ILOG("Got MIDI Data: %02x %02x %02x", cmd[0], cmd[1], cmd[2]);
|
||||
listener->midiEvent(cmd);
|
||||
break;
|
||||
default:
|
||||
WLOG("Got unexpected MIDI message: %08x", (uint32_t)wMsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MidiDevice MidiInStart(int deviceID, MidiListener *listener) {
|
||||
HMIDIIN hMidiIn;
|
||||
MMRESULT result = midiInOpen(&hMidiIn, deviceID, (DWORD_PTR)(&MidiCallback), (DWORD_PTR)listener, CALLBACK_FUNCTION);
|
||||
midiInStart(hMidiIn);
|
||||
return (MidiDevice)hMidiIn;
|
||||
HMIDIIN hMidiIn;
|
||||
MMRESULT result = midiInOpen(&hMidiIn, deviceID, (DWORD_PTR)(&MidiCallback), (DWORD_PTR)listener, CALLBACK_FUNCTION);
|
||||
midiInStart(hMidiIn);
|
||||
return (MidiDevice)hMidiIn;
|
||||
}
|
||||
|
||||
void MidiInStop(MidiDevice device) {
|
||||
HMIDIIN hMidiIn = (HMIDIIN)device;
|
||||
midiInStop(hMidiIn);
|
||||
midiInClose(hMidiIn);
|
||||
HMIDIIN hMidiIn = (HMIDIIN)device;
|
||||
midiInStop(hMidiIn);
|
||||
midiInClose(hMidiIn);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -74,15 +73,15 @@ void MidiInStop(MidiDevice device) {
|
||||
// Stubs for other platforms.
|
||||
|
||||
std::vector<std::string> MidiInGetDevices() {
|
||||
return std::vector<std::string>();
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
MidiDevice MidiInStart(int deviceID, MidiListener *listener) {
|
||||
FLOG("Invalid MIDI device");
|
||||
FLOG("Invalid MIDI device");
|
||||
}
|
||||
|
||||
void MidiInStop(MidiDevice device) {
|
||||
FLOG("Invalid MIDI device");
|
||||
FLOG("Invalid MIDI device");
|
||||
}
|
||||
|
||||
#endif
|
||||
+2
-1
@@ -16,7 +16,8 @@ typedef void *MidiDevice;
|
||||
class MidiListener
|
||||
{
|
||||
public:
|
||||
virtual void midiEvent(const uint8_t *cmd) = 0;
|
||||
virtual ~MidiListener() {}
|
||||
virtual void midiEvent(const uint8_t *cmd) = 0;
|
||||
};
|
||||
|
||||
// Gets the names of the devices in a vector. The device identifier is the index in the vector.
|
||||
|
||||
+19
-2
@@ -62,6 +62,9 @@
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>Ws2_32.lib</AdditionalDependencies>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
@@ -80,6 +83,9 @@
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>Ws2_32.lib</AdditionalDependencies>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<None Include="file\CMakeLists.txt" />
|
||||
@@ -89,6 +95,7 @@
|
||||
<ClInclude Include="audio\mixer.h" />
|
||||
<ClInclude Include="audio\wav_read.h" />
|
||||
<ClInclude Include="base\basictypes.h" />
|
||||
<ClInclude Include="base\buffer.h" />
|
||||
<ClInclude Include="base\color.h" />
|
||||
<ClInclude Include="base\colorutil.h" />
|
||||
<ClInclude Include="base\display.h" />
|
||||
@@ -101,6 +108,7 @@
|
||||
<ClInclude Include="base\stats.h" />
|
||||
<ClInclude Include="base\stringutil.h" />
|
||||
<ClInclude Include="base\timeutil.h" />
|
||||
<ClInclude Include="data\listable.h" />
|
||||
<ClInclude Include="ext\etcpack\etcdec.h" />
|
||||
<ClInclude Include="ext\etcpack\etcpack.h" />
|
||||
<ClInclude Include="ext\sha1\sha1.h" />
|
||||
@@ -110,6 +118,7 @@
|
||||
<ClInclude Include="file\chunk_file.h" />
|
||||
<ClInclude Include="file\dialog.h" />
|
||||
<ClInclude Include="file\easy_file.h" />
|
||||
<ClInclude Include="file\fd_util.h" />
|
||||
<ClInclude Include="file\file_util.h" />
|
||||
<ClInclude Include="file\vfs.h" />
|
||||
<ClInclude Include="file\zip_read.h" />
|
||||
@@ -123,7 +132,6 @@
|
||||
<ClInclude Include="gfx_es2\glsl_program.h" />
|
||||
<ClInclude Include="gfx_es2\vertex_format.h" />
|
||||
<ClInclude Include="image\png_load.h" />
|
||||
<ClInclude Include="image\surface.h" />
|
||||
<ClInclude Include="image\zim_load.h" />
|
||||
<ClInclude Include="image\zim_save.h" />
|
||||
<ClInclude Include="input\gesture_detector.h" />
|
||||
@@ -135,8 +143,11 @@
|
||||
<ClInclude Include="math\lin\vec3.h" />
|
||||
<ClInclude Include="math\math_util.h" />
|
||||
<ClInclude Include="midi\midi_input.h" />
|
||||
<ClInclude Include="net\http_client.h" />
|
||||
<ClInclude Include="net\resolve.h" />
|
||||
<ClInclude Include="profiler\profiler.h" />
|
||||
<ClInclude Include="ui\ui.h" />
|
||||
<ClInclude Include="util\bits\bits.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="android\app-android.cpp">
|
||||
@@ -145,10 +156,12 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="audio\mixer.cpp" />
|
||||
<ClCompile Include="audio\wav_read.cpp" />
|
||||
<ClCompile Include="base\buffer.cpp" />
|
||||
<ClCompile Include="base\colorutil.cpp" />
|
||||
<ClCompile Include="base\display.cpp" />
|
||||
<ClCompile Include="base\error_context.cpp" />
|
||||
<ClCompile Include="base\LAMEString.cpp" />
|
||||
<ClCompile Include="base\stringutil.cpp" />
|
||||
<ClCompile Include="base\timeutil.cpp" />
|
||||
<ClCompile Include="ext\etcpack\etcdec.cpp" />
|
||||
<ClCompile Include="ext\etcpack\etcpack.cpp" />
|
||||
@@ -163,6 +176,7 @@
|
||||
<ClCompile Include="file\chunk_file.cpp" />
|
||||
<ClCompile Include="file\dialog.cpp" />
|
||||
<ClCompile Include="file\easy_file.cpp" />
|
||||
<ClCompile Include="file\fd_util.cpp" />
|
||||
<ClCompile Include="file\file_util.cpp" />
|
||||
<ClCompile Include="file\zip_read.cpp" />
|
||||
<ClCompile Include="gfx\gl_debug_log.cpp" />
|
||||
@@ -182,10 +196,13 @@
|
||||
<ClCompile Include="math\lin\matrix4x4.cpp" />
|
||||
<ClCompile Include="math\lin\quat.cpp" />
|
||||
<ClCompile Include="math\lin\vec3.cpp" />
|
||||
<ClCompile Include="math\math_util.cc" />
|
||||
<ClCompile Include="math\math_util.cpp" />
|
||||
<ClCompile Include="midi\midi_input.cpp" />
|
||||
<ClCompile Include="net\http_client.cpp" />
|
||||
<ClCompile Include="net\resolve.cpp" />
|
||||
<ClCompile Include="profiler\profiler.cpp" />
|
||||
<ClCompile Include="ui\ui.cpp" />
|
||||
<ClCompile Include="util\bits\bits.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
+54
-5
@@ -7,8 +7,6 @@
|
||||
<None Include="README.md" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="base\logging.h" />
|
||||
<ClInclude Include="image\surface.h" />
|
||||
<ClInclude Include="gfx\gl_debug_log.h">
|
||||
<Filter>gfx</Filter>
|
||||
</ClInclude>
|
||||
@@ -156,6 +154,27 @@
|
||||
<ClInclude Include="base\mutex.h">
|
||||
<Filter>base</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\bits\bits.h">
|
||||
<Filter>util</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="data\listable.h">
|
||||
<Filter>data</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="base\logging.h">
|
||||
<Filter>base</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="net\http_client.h">
|
||||
<Filter>net</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="base\buffer.h">
|
||||
<Filter>base</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="file\fd_util.h">
|
||||
<Filter>file</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="net\resolve.h">
|
||||
<Filter>net</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="gfx\gl_debug_log.cpp">
|
||||
@@ -218,9 +237,6 @@
|
||||
<ClCompile Include="gfx\texture_atlas.cpp">
|
||||
<Filter>gfx</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="math\math_util.cc">
|
||||
<Filter>math</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ext\etcpack\etcpack.cpp">
|
||||
<Filter>ext</Filter>
|
||||
</ClCompile>
|
||||
@@ -281,6 +297,27 @@
|
||||
<ClCompile Include="android\app-android.cpp">
|
||||
<Filter>base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util\bits\bits.cpp">
|
||||
<Filter>util</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="math\math_util.cpp">
|
||||
<Filter>math</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="net\http_client.cpp">
|
||||
<Filter>net</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="base\buffer.cpp">
|
||||
<Filter>base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="file\fd_util.cpp">
|
||||
<Filter>file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="base\stringutil.cpp">
|
||||
<Filter>base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="net\resolve.cpp">
|
||||
<Filter>net</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="gfx">
|
||||
@@ -322,5 +359,17 @@
|
||||
<Filter Include="midi">
|
||||
<UniqueIdentifier>{4710a9a2-d1fa-4920-ba1b-a7527902be53}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="util">
|
||||
<UniqueIdentifier>{e36ca540-863c-496b-b0f4-b1ece3e72feb}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="data">
|
||||
<UniqueIdentifier>{d5fa3d62-88bf-4dc4-9814-28f3c0444e62}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="io">
|
||||
<UniqueIdentifier>{1e85f968-7106-483c-ae7d-77d0ef58d787}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="net">
|
||||
<UniqueIdentifier>{6a548b3d-3a4c-4114-aa2f-0b42bf7bf2ce}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,11 @@
|
||||
set(SRCS
|
||||
http_client.cpp
|
||||
resolve.cpp)
|
||||
|
||||
set(SRCS ${SRCS})
|
||||
|
||||
add_library(net STATIC ${SRCS})
|
||||
|
||||
if(UNIX)
|
||||
add_definitions(-fPIC)
|
||||
endif(UNIX)
|
||||
@@ -0,0 +1,147 @@
|
||||
#include "net/http_client.h"
|
||||
|
||||
// for inet_pton
|
||||
#define _WIN32_WINNT 0x600
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#define closesocket close
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/buffer.h"
|
||||
#include "base/stringutil.h"
|
||||
#include "net/resolve.h"
|
||||
// #include "strings/strutil.h"
|
||||
|
||||
namespace net {
|
||||
|
||||
Connection::Connection()
|
||||
: port_(-1), sock_(-1) {
|
||||
}
|
||||
|
||||
Connection::~Connection() {
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
bool Connection::Resolve(const char *host, int port) {
|
||||
CHECK_EQ(-1, sock_);
|
||||
host_ = host;
|
||||
port_ = port;
|
||||
|
||||
const char *ip = net::DNSResolve(host);
|
||||
// VLOG(1) << "Resolved " << host << " to " << ip;
|
||||
remote_.sin_family = AF_INET;
|
||||
int tmpres = inet_pton(AF_INET, ip, (void *)(&(remote_.sin_addr.s_addr)));
|
||||
CHECK_GE(tmpres, 0); // << "inet_pton failed";
|
||||
CHECK_NE(0, tmpres); // << ip << " not a valid IP address";
|
||||
remote_.sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Connection::Connect() {
|
||||
CHECK_GE(port_, 0);
|
||||
sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
CHECK_GE(sock_, 0);
|
||||
//VLOG(1) << "Connecting to " << host_ << ":" << port_;
|
||||
|
||||
// poll once per second.. should find a way to do this blocking.
|
||||
int retval = -1;
|
||||
while (retval < 0) {
|
||||
retval = connect(sock_, (sockaddr *)&remote_, sizeof(struct sockaddr));
|
||||
if (retval >= 0) break;
|
||||
#ifdef _WIN32
|
||||
Sleep(1);
|
||||
#else
|
||||
sleep(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::Disconnect() {
|
||||
if (sock_ != -1) {
|
||||
closesocket(sock_);
|
||||
sock_ = -1;
|
||||
} else {
|
||||
WLOG("Socket was already disconnected.");
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::Reconnect() {
|
||||
Disconnect();
|
||||
Connect();
|
||||
}
|
||||
|
||||
} // net
|
||||
|
||||
namespace http {
|
||||
|
||||
Client::Client() {
|
||||
}
|
||||
Client::~Client() {
|
||||
}
|
||||
|
||||
#define USERAGENT "METAGET 1.0"
|
||||
|
||||
void Client::GET(const char *resource, Buffer *output) {
|
||||
Buffer buffer;
|
||||
const char *tpl = "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n";
|
||||
buffer.Printf(tpl, resource, host_.c_str());
|
||||
CHECK(buffer.FlushSocket(sock()));
|
||||
|
||||
// Snarf all the data we can.
|
||||
output->ReadAll(sock());
|
||||
|
||||
// Skip the header.
|
||||
while (output->SkipLineCRLF() > 0)
|
||||
;
|
||||
|
||||
// output now contains the rest of the reply.
|
||||
}
|
||||
|
||||
int Client::POST(const char *resource, const std::string &data, Buffer *output) {
|
||||
Buffer buffer;
|
||||
const char *tpl = "POST %s HTTP/1.0\r\nContent-Length: %d\r\n\r\n";
|
||||
buffer.Printf(tpl, resource, (int)data.size());
|
||||
buffer.Append(data);
|
||||
CHECK(buffer.Flush(sock()));
|
||||
|
||||
// I guess we could add a deadline here.
|
||||
output->ReadAll(sock());
|
||||
|
||||
if (output->size() == 0) {
|
||||
// The connection was closed.
|
||||
ELOG("POST failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string debug_data;
|
||||
output->PeekAll(&debug_data);
|
||||
|
||||
//VLOG(1) << "Reply size (before stripping headers): " << debug_data.size();
|
||||
std::string debug_str;
|
||||
StringToHexString(debug_data, &debug_str);
|
||||
// Tear off the http headers, leaving the actual response data.
|
||||
std::string firstline;
|
||||
CHECK_GT(output->TakeLineCRLF(&firstline), 0);
|
||||
int code = atoi(&firstline[9]); // ugggly hardcoding
|
||||
//VLOG(1) << "HTTP result code: " << code;
|
||||
while (true) {
|
||||
int skipped = output->SkipLineCRLF();
|
||||
if (skipped == 0)
|
||||
break;
|
||||
}
|
||||
output->PeekAll(&debug_data);
|
||||
return code;
|
||||
}
|
||||
|
||||
} // http
|
||||
@@ -0,0 +1,66 @@
|
||||
#ifndef _NET_HTTP_HTTP_CLIENT
|
||||
#define _NET_HTTP_HTTP_CLIENT
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/buffer.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
namespace net {
|
||||
|
||||
class Connection {
|
||||
public:
|
||||
Connection();
|
||||
virtual ~Connection();
|
||||
|
||||
// Inits the sockaddr_in.
|
||||
bool Resolve(const char *host, int port);
|
||||
|
||||
void Connect();
|
||||
void Disconnect();
|
||||
|
||||
// Disconnects, and connects. Doesn't re-resolve.
|
||||
void Reconnect();
|
||||
|
||||
// Only to be used for bring-up and debugging.
|
||||
uintptr_t sock() const { return sock_; }
|
||||
|
||||
protected:
|
||||
// Store the remote host here, so we can send it along through HTTP/1.1 requests.
|
||||
// TODO: Move to http::client?
|
||||
std::string host_;
|
||||
int port_;
|
||||
|
||||
sockaddr_in remote_;
|
||||
|
||||
private:
|
||||
uintptr_t sock_;
|
||||
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
||||
namespace http {
|
||||
|
||||
class Client : public net::Connection {
|
||||
public:
|
||||
Client();
|
||||
~Client();
|
||||
|
||||
void GET(const char *resource, Buffer *output);
|
||||
|
||||
// Return value is the HTTP return code.
|
||||
int POST(const char *resource, const std::string &data, Buffer *output);
|
||||
|
||||
// HEAD, PUT, DELETE aren't implemented yet.
|
||||
};
|
||||
|
||||
} // http
|
||||
|
||||
#endif // _NET_HTTP_HTTP_CLIENT
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "net/resolve.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h> // gethostbyname
|
||||
#else
|
||||
#include <WinSock2.h>
|
||||
#include <Ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace net {
|
||||
|
||||
|
||||
void Init()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData = {0};
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
#endif
|
||||
}
|
||||
|
||||
char *DNSResolve(const char *host)
|
||||
{
|
||||
struct hostent *hent;
|
||||
if((hent = gethostbyname(host)) == NULL)
|
||||
{
|
||||
perror("Can't get IP");
|
||||
exit(1);
|
||||
}
|
||||
int iplen = 15; //XXX.XXX.XXX.XXX
|
||||
char *ip = (char *)malloc(iplen+1);
|
||||
memset(ip, 0, iplen+1);
|
||||
if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL)
|
||||
{
|
||||
perror("Can't resolve host");
|
||||
exit(1);
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef _NET_RESOLVE_H
|
||||
#define _NET_RESOLVE_H
|
||||
|
||||
namespace net {
|
||||
|
||||
// Required on Win32
|
||||
void Init();
|
||||
|
||||
// use free() to free the returned string.
|
||||
char *DNSResolve(const char *host);
|
||||
} // namespace net
|
||||
#endif
|
||||
@@ -42,7 +42,7 @@ void _profiler_leave(const char *section_name) {
|
||||
cur_section[level].end = real_time_now();
|
||||
if (strcmp(section_name, cur_section[level].name)) {
|
||||
FLOG("Can't enter %s when %s is active, only one at a time!",
|
||||
section_name, cur_section[level].name);
|
||||
section_name, cur_section[level].name);
|
||||
}
|
||||
cur_section[level].level = level;
|
||||
current_frame.push_back(cur_section[level]);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "gfx/texture_atlas.h"
|
||||
#include "gfx_es2/draw_buffer.h"
|
||||
|
||||
// TODO: UI should probably not own these.
|
||||
DrawBuffer ui_draw2d;
|
||||
DrawBuffer ui_draw2d_front;
|
||||
UIState uistate;
|
||||
@@ -19,31 +20,36 @@ static int themeCheckOnImage;
|
||||
static int themeCheckOffImage;
|
||||
|
||||
void UIInit(const Atlas *atlas, int uiFont, int buttonImage, int checkOn, int checkOff) {
|
||||
ui_draw2d.SetAtlas(atlas);
|
||||
ui_draw2d.SetAtlas(atlas);
|
||||
ui_draw2d_front.SetAtlas(atlas);
|
||||
themeAtlas = atlas;
|
||||
themeUIFont = uiFont;
|
||||
themeButtonImage = buttonImage;
|
||||
themeCheckOnImage = checkOn;
|
||||
themeCheckOffImage = checkOff;
|
||||
themeAtlas = atlas;
|
||||
themeUIFont = uiFont;
|
||||
themeButtonImage = buttonImage;
|
||||
themeCheckOnImage = checkOn;
|
||||
themeCheckOffImage = checkOff;
|
||||
memset(&uistate, 0, sizeof(uistate));
|
||||
}
|
||||
|
||||
void UIUpdateMouse(int i, float x, float y, bool down) {
|
||||
if (down && !uistate.mousedown[i]) {
|
||||
uistate.mousepressed[i] = 1;
|
||||
uistate.mouseStartX[i] = x;
|
||||
uistate.mouseStartY[i] = y;
|
||||
} else {
|
||||
uistate.mousepressed[i] = 0;
|
||||
}
|
||||
if (down && !uistate.mousedown[i]) {
|
||||
uistate.mousepressed[i] = 1;
|
||||
uistate.mouseStartX[i] = x;
|
||||
uistate.mouseStartY[i] = y;
|
||||
} else {
|
||||
uistate.mousepressed[i] = 0;
|
||||
}
|
||||
if (uistate.mousedown[i])
|
||||
uistate.mouseframesdown[i]++;
|
||||
else
|
||||
uistate.mouseframesdown[i] = 0;
|
||||
|
||||
uistate.mousex[i] = x;
|
||||
uistate.mousey[i] = y;
|
||||
uistate.mousedown[i] = down;
|
||||
uistate.mousex[i] = x;
|
||||
uistate.mousey[i] = y;
|
||||
uistate.mousedown[i] = down;
|
||||
}
|
||||
|
||||
bool UIRegionHit(int i, int x, int y, int w, int h, int margin) {
|
||||
// Input handling
|
||||
// Input handling
|
||||
if (uistate.mousex[i] < x - margin ||
|
||||
uistate.mousey[i] < y - margin ||
|
||||
uistate.mousex[i] >= x + w + margin ||
|
||||
@@ -55,245 +61,248 @@ bool UIRegionHit(int i, int x, int y, int w, int h, int margin) {
|
||||
}
|
||||
|
||||
void UIBegin() {
|
||||
for (int i = 0; i < MAX_POINTERS; i++)
|
||||
uistate.hotitem[i] = 0;
|
||||
for (int i = 0; i < MAX_POINTERS; i++)
|
||||
uistate.hotitem[i] = 0;
|
||||
ui_draw2d.Begin();
|
||||
ui_draw2d_front.Begin();
|
||||
ui_draw2d_front.Begin();
|
||||
}
|
||||
|
||||
void UIEnd() {
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
if (uistate.mousedown[i] == 0) {
|
||||
uistate.activeitem[i] = 0;
|
||||
} else {
|
||||
if (uistate.activeitem[i] == 0) {
|
||||
uistate.activeitem[i] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_draw2d.End();
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
if (uistate.mousedown[i] == 0) {
|
||||
uistate.activeitem[i] = 0;
|
||||
} else {
|
||||
if (uistate.activeitem[i] == 0) {
|
||||
uistate.activeitem[i] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_draw2d.End();
|
||||
ui_draw2d_front.End();
|
||||
|
||||
if (uistate.ui_tick > 0)
|
||||
uistate.ui_tick--;
|
||||
}
|
||||
|
||||
void UIText(int x, int y, const char *text, uint32_t color, float scale, int align) {
|
||||
UIText(themeUIFont, x, y, text, color, scale, align);
|
||||
UIText(themeUIFont, x, y, text, color, scale, align);
|
||||
}
|
||||
|
||||
void UIText(int font, int x, int y, const char *text, uint32_t color, float scale, int align) {
|
||||
ui_draw2d.SetFontScale(scale, scale);
|
||||
ui_draw2d.DrawTextShadow(font, text, x, y, color, align);
|
||||
ui_draw2d.SetFontScale(1.0f, 1.0f);
|
||||
ui_draw2d.SetFontScale(scale, scale);
|
||||
ui_draw2d.DrawTextShadow(font, text, x, y, color, align);
|
||||
ui_draw2d.SetFontScale(1.0f, 1.0f);
|
||||
}
|
||||
|
||||
int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align) {
|
||||
float h = themeAtlas->images[themeButtonImage].h;
|
||||
|
||||
float x, y;
|
||||
layout.GetPos(&w, &h, &x, &y);
|
||||
|
||||
if (button_align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (button_align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (button_align & ALIGN_RIGHT) x -= w;
|
||||
if (button_align & ALIGN_BOTTOMRIGHT) y -= h;
|
||||
float x, y;
|
||||
layout.GetPos(&w, &h, &x, &y);
|
||||
|
||||
int txOffset = 0;
|
||||
if (button_align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (button_align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (button_align & ALIGN_RIGHT) x -= w;
|
||||
if (button_align & ALIGN_BOTTOMRIGHT) y -= h;
|
||||
|
||||
int clicked = 0;
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check whether the button should be hot, use a generous margin for touch ease
|
||||
if (UIRegionHit(i, x, y, w, h, 8)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
int txOffset = 0;
|
||||
|
||||
if (uistate.hotitem[i] == id) {
|
||||
if (uistate.activeitem[i] == id) {
|
||||
// Button is both 'hot' and 'active'
|
||||
txOffset = 2;
|
||||
} else {
|
||||
// Button is merely 'hot'
|
||||
}
|
||||
} else {
|
||||
// button is not hot, but it may be active
|
||||
}
|
||||
int clicked = 0;
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check whether the button should be hot, use a generous margin for touch ease
|
||||
if (UIRegionHit(i, x, y, w, h, 8)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
|
||||
if (uistate.hotitem[i] == id) {
|
||||
if (uistate.activeitem[i] == id) {
|
||||
// Button is both 'hot' and 'active'
|
||||
txOffset = 2;
|
||||
} else {
|
||||
// Button is merely 'hot'
|
||||
}
|
||||
} else {
|
||||
// button is not hot, but it may be active
|
||||
}
|
||||
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id) {
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id) {
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Render button
|
||||
|
||||
ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w);
|
||||
ui_draw2d.DrawTextShadow(themeUIFont, text, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER);
|
||||
|
||||
uistate.lastwidget = id;
|
||||
return clicked;
|
||||
uistate.lastwidget = id;
|
||||
return clicked;
|
||||
}
|
||||
|
||||
int UIImageButton(int id, const LayoutManager &layout, float w, int image, int button_align) {
|
||||
float h = 64;
|
||||
float x, y;
|
||||
layout.GetPos(&w, &h, &x, &y);
|
||||
float h = 64;
|
||||
float x, y;
|
||||
layout.GetPos(&w, &h, &x, &y);
|
||||
|
||||
if (button_align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (button_align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (button_align & ALIGN_RIGHT) x -= w;
|
||||
if (button_align & ALIGN_BOTTOMRIGHT) y -= h;
|
||||
if (button_align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (button_align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (button_align & ALIGN_RIGHT) x -= w;
|
||||
if (button_align & ALIGN_BOTTOMRIGHT) y -= h;
|
||||
|
||||
int txOffset = 0;
|
||||
int clicked = 0;
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check whether the button should be hot, use a generous margin for touch ease
|
||||
if (UIRegionHit(i, x, y, w, h, 8)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
int txOffset = 0;
|
||||
int clicked = 0;
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check whether the button should be hot, use a generous margin for touch ease
|
||||
if (UIRegionHit(i, x, y, w, h, 8)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
|
||||
if (uistate.hotitem[i] == id) {
|
||||
if (uistate.activeitem[i] == id) {
|
||||
// Button is both 'hot' and 'active'
|
||||
txOffset = 2;
|
||||
} else {
|
||||
// Button is merely 'hot'
|
||||
}
|
||||
} else {
|
||||
// button is not hot, but it may be active
|
||||
}
|
||||
if (uistate.hotitem[i] == id) {
|
||||
if (uistate.activeitem[i] == id) {
|
||||
// Button is both 'hot' and 'active'
|
||||
txOffset = 2;
|
||||
} else {
|
||||
// Button is merely 'hot'
|
||||
}
|
||||
} else {
|
||||
// button is not hot, but it may be active
|
||||
}
|
||||
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id) {
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id) {
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Render button
|
||||
// Render button
|
||||
|
||||
ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w);
|
||||
ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 1.0f, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER);
|
||||
ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w);
|
||||
ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 1.0f, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER);
|
||||
|
||||
uistate.lastwidget = id;
|
||||
return clicked;
|
||||
uistate.lastwidget = id;
|
||||
return clicked;
|
||||
}
|
||||
|
||||
|
||||
int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) {
|
||||
const int h = 64;
|
||||
float tw, th;
|
||||
ui_draw2d.MeasureText(themeUIFont, text, &tw, &th);
|
||||
int w = themeAtlas->images[themeCheckOnImage].w + UI_SPACE + tw;
|
||||
if (align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (align & ALIGN_RIGHT) x -= w;
|
||||
if (align & ALIGN_BOTTOMRIGHT) y -= h;
|
||||
float tw, th;
|
||||
ui_draw2d.MeasureText(themeUIFont, text, &tw, &th);
|
||||
int w = themeAtlas->images[themeCheckOnImage].w + UI_SPACE + tw;
|
||||
if (align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (align & ALIGN_RIGHT) x -= w;
|
||||
if (align & ALIGN_BOTTOMRIGHT) y -= h;
|
||||
|
||||
int txOffset = 0;
|
||||
int clicked = 0;
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
int txOffset = 0;
|
||||
int clicked = 0;
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
|
||||
// Check whether the button should be hot
|
||||
if (UIRegionHit(i, x, y, w, h, 8)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
|
||||
// Render button
|
||||
// Check whether the button should be hot
|
||||
if (UIRegionHit(i, x, y, w, h, 8)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
|
||||
if (uistate.hotitem[i] == id) {
|
||||
if (uistate.activeitem[i] == id) {
|
||||
// Button is both 'hot' and 'active'
|
||||
txOffset = 2;
|
||||
} else {
|
||||
// Button is merely 'hot'
|
||||
}
|
||||
} else {
|
||||
// button is not hot, but it may be active
|
||||
}
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id) {
|
||||
*value = !(*value);
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
// Render button
|
||||
|
||||
ui_draw2d.DrawImage((*value) ? themeCheckOnImage : themeCheckOffImage, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
|
||||
if (uistate.hotitem[i] == id) {
|
||||
if (uistate.activeitem[i] == id) {
|
||||
// Button is both 'hot' and 'active'
|
||||
txOffset = 2;
|
||||
} else {
|
||||
// Button is merely 'hot'
|
||||
}
|
||||
} else {
|
||||
// button is not hot, but it may be active
|
||||
}
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id) {
|
||||
*value = !(*value);
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ui_draw2d.DrawImage((*value) ? themeCheckOnImage : themeCheckOffImage, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
|
||||
ui_draw2d.DrawTextShadow(themeUIFont, text, x + themeAtlas->images[themeCheckOnImage].w + UI_SPACE, y + txOffset + h/2, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
|
||||
|
||||
|
||||
uistate.lastwidget = id;
|
||||
return clicked;
|
||||
uistate.lastwidget = id;
|
||||
return clicked;
|
||||
}
|
||||
|
||||
void StringVectorListAdapter::drawItem(int item, int x, int y, int w, int h, bool selected) const
|
||||
{
|
||||
ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w);
|
||||
ui_draw2d.DrawTextShadow(themeUIFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
|
||||
ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w);
|
||||
ui_draw2d.DrawTextShadow(themeUIFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
|
||||
}
|
||||
|
||||
int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListState *state) {
|
||||
const int item_h = 64;
|
||||
|
||||
int clicked = 0;
|
||||
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check whether the button should be hot
|
||||
if (UIRegionHit(i, x, y, w, h, 0)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
int clicked = 0;
|
||||
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id &&
|
||||
state->selected != -1) {
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check whether the button should be hot
|
||||
if (UIRegionHit(i, x, y, w, h, 0)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
|
||||
// render items
|
||||
int itemHeight = adapter->itemHeight(0);
|
||||
int numItems = adapter->getCount();
|
||||
for (int i = 0; i < numItems; i++) {
|
||||
int item_y = y + i * itemHeight - state->scrollY;
|
||||
if (uistate.mousedown && adapter->itemEnabled(i) && item_y >= y - itemHeight && item_y <= y + h &&
|
||||
UIRegionHit(i, x, item_y, w, h, 0)) {
|
||||
// ultra fast touch response
|
||||
state->selected = i;
|
||||
}
|
||||
adapter->drawItem(i, x, item_y, w, itemHeight, i == state->selected);
|
||||
}
|
||||
uistate.lastwidget = id;
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id &&
|
||||
state->selected != -1) {
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, no clicky.
|
||||
// render items
|
||||
int itemHeight = adapter->itemHeight(0);
|
||||
int numItems = adapter->getCount();
|
||||
for (int i = 0; i < numItems; i++) {
|
||||
int item_y = y + i * itemHeight - state->scrollY;
|
||||
if (uistate.mousedown && adapter->itemEnabled(i) && item_y >= y - itemHeight && item_y <= y + h &&
|
||||
UIRegionHit(i, x, item_y, w, h, 0)) {
|
||||
// ultra fast touch response
|
||||
state->selected = i;
|
||||
}
|
||||
adapter->drawItem(i, x, item_y, w, itemHeight, i == state->selected);
|
||||
}
|
||||
uistate.lastwidget = id;
|
||||
|
||||
// Otherwise, no clicky.
|
||||
return clicked;
|
||||
}
|
||||
|
||||
/*
|
||||
struct SlideItem {
|
||||
const char *text;
|
||||
int image;
|
||||
uint32_t bgColor;
|
||||
const char *text;
|
||||
int image;
|
||||
uint32_t bgColor;
|
||||
};
|
||||
|
||||
struct SlideState
|
||||
{
|
||||
float scroll;
|
||||
float scroll;
|
||||
|
||||
};
|
||||
|
||||
@@ -306,29 +315,29 @@ int UIHSlider(int id, int x, int y, int w, int max, int *value) {
|
||||
// Calculate mouse cursor's relative y offset
|
||||
int xpos = ((256 - 16) * *value) / max;
|
||||
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check for hotness
|
||||
if (UIRegionHit(i, x+8, y+8, 16, 255, 0)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check for hotness
|
||||
if (UIRegionHit(i, x+8, y+8, 16, 255, 0)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
|
||||
// Update widget value
|
||||
if (uistate.activeitem[i] == id) {
|
||||
int mousepos = uistate.mousey[i] - (y + 8);
|
||||
if (mousepos < 0) mousepos = 0;
|
||||
if (mousepos > 255) mousepos = 255;
|
||||
int v = (mousepos * max) / 255;
|
||||
if (v != *value) {
|
||||
*value = v;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Update widget value
|
||||
if (uistate.activeitem[i] == id) {
|
||||
int mousepos = uistate.mousey[i] - (y + 8);
|
||||
if (mousepos < 0) mousepos = 0;
|
||||
if (mousepos > 255) mousepos = 255;
|
||||
int v = (mousepos * max) / 255;
|
||||
if (v != *value) {
|
||||
*value = v;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Render the scrollbar
|
||||
ui_draw2d.Rect(x, y, 32, 256+16, 0x777777);
|
||||
|
||||
|
||||
ui_draw2d.Rect(x+8+xpos, y+8, 16, 16, 0xffffff);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -27,49 +27,52 @@
|
||||
|
||||
class LayoutManager {
|
||||
public:
|
||||
virtual void GetPos(float *w, float *h, float *x, float *y) const = 0;
|
||||
virtual void GetPos(float *w, float *h, float *x, float *y) const = 0;
|
||||
};
|
||||
|
||||
class Pos : public LayoutManager {
|
||||
public:
|
||||
Pos(float x, float y) : x_(x), y_(y) {}
|
||||
virtual void GetPos(float *w, float *h, float *x, float *y) const {
|
||||
*x = x_;
|
||||
*y = y_;
|
||||
}
|
||||
Pos(float x, float y) : x_(x), y_(y) {}
|
||||
virtual void GetPos(float *w, float *h, float *x, float *y) const {
|
||||
*x = x_;
|
||||
*y = y_;
|
||||
}
|
||||
private:
|
||||
float x_;
|
||||
float y_;
|
||||
float x_;
|
||||
float y_;
|
||||
};
|
||||
|
||||
class HLinear : public LayoutManager {
|
||||
public:
|
||||
HLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {}
|
||||
virtual void GetPos(float *w, float *h, float *x, float *y) const {
|
||||
*x = x_;
|
||||
*y = y_;
|
||||
x_ += *w + spacing_;
|
||||
}
|
||||
HLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {}
|
||||
virtual void GetPos(float *w, float *h, float *x, float *y) const {
|
||||
*x = x_;
|
||||
*y = y_;
|
||||
x_ += *w + spacing_;
|
||||
}
|
||||
void Space(float x) {
|
||||
x_ += x;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable float x_;
|
||||
float y_;
|
||||
float spacing_;
|
||||
mutable float x_;
|
||||
float y_;
|
||||
float spacing_;
|
||||
};
|
||||
|
||||
class VLinear : public LayoutManager {
|
||||
public:
|
||||
VLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {}
|
||||
virtual void GetPos(float *w, float *h, float *x, float *y) const {
|
||||
*x = x_;
|
||||
*y = y_;
|
||||
y_ += *h + spacing_;
|
||||
}
|
||||
VLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {}
|
||||
virtual void GetPos(float *w, float *h, float *x, float *y) const {
|
||||
*x = x_;
|
||||
*y = y_;
|
||||
y_ += *h + spacing_;
|
||||
}
|
||||
|
||||
private:
|
||||
float x_;
|
||||
mutable float y_;
|
||||
float spacing_;
|
||||
float x_;
|
||||
mutable float y_;
|
||||
float spacing_;
|
||||
};
|
||||
|
||||
#ifndef MAX_POINTERS
|
||||
@@ -78,25 +81,29 @@ private:
|
||||
|
||||
// Mouse out of habit, applies just as well to touch events.
|
||||
// UI does not yet support multitouch.
|
||||
// This struct is zeroed on init, so should be valid at that state.
|
||||
struct UIState {
|
||||
int mousex[MAX_POINTERS];
|
||||
int mousey[MAX_POINTERS];
|
||||
int mousedown[MAX_POINTERS];
|
||||
int mousepressed[MAX_POINTERS];
|
||||
bool mousedown[MAX_POINTERS];
|
||||
bool mousepressed[MAX_POINTERS];
|
||||
short mouseframesdown[MAX_POINTERS];
|
||||
|
||||
int mouseStartX[MAX_POINTERS];
|
||||
int mouseStartY[MAX_POINTERS];
|
||||
int mouseStartX[MAX_POINTERS];
|
||||
int mouseStartY[MAX_POINTERS];
|
||||
|
||||
int hotitem[MAX_POINTERS];
|
||||
int hotitem[MAX_POINTERS];
|
||||
int activeitem[MAX_POINTERS];
|
||||
|
||||
// keyboard focus, not currently used
|
||||
int kbdwidget;
|
||||
int lastwidget;
|
||||
// keyboard focus, not currently used
|
||||
int kbdwidget;
|
||||
int lastwidget;
|
||||
|
||||
// Used by controls that need to keep track of the initial value for drags, for example.
|
||||
// Should probably be indexed by finger - would be neat to be able to move two knobs at the same time.
|
||||
float tempfloat;
|
||||
// Used by controls that need to keep track of the initial value for drags, for example.
|
||||
// Should probably be indexed by finger - would be neat to be able to move two knobs at the same time.
|
||||
float tempfloat;
|
||||
|
||||
int ui_tick;
|
||||
};
|
||||
|
||||
// This needs to be extern so that additional UI controls can be developed outside this file.
|
||||
@@ -118,38 +125,38 @@ const int LARGE_BUTTON_WIDTH = 192;
|
||||
const int BUTTON_HEIGHT = 72;
|
||||
|
||||
struct SlideItem {
|
||||
const char *text;
|
||||
int image;
|
||||
uint32_t bgColor;
|
||||
const char *text;
|
||||
int image;
|
||||
uint32_t bgColor;
|
||||
};
|
||||
|
||||
struct UISlideState {
|
||||
float scroll;
|
||||
float scroll;
|
||||
};
|
||||
|
||||
// Implement this interface to style your lists
|
||||
class UIListAdapter {
|
||||
public:
|
||||
virtual size_t getCount() const = 0;
|
||||
virtual void drawItem(int item, int x, int y, int w, int h, bool active) const = 0;
|
||||
virtual float itemHeight(int itemIndex) const { return 64; }
|
||||
virtual bool itemEnabled(int itemIndex) const { return true; }
|
||||
virtual size_t getCount() const = 0;
|
||||
virtual void drawItem(int item, int x, int y, int w, int h, bool active) const = 0;
|
||||
virtual float itemHeight(int itemIndex) const { return 64; }
|
||||
virtual bool itemEnabled(int itemIndex) const { return true; }
|
||||
};
|
||||
|
||||
class StringVectorListAdapter : public UIListAdapter {
|
||||
public:
|
||||
StringVectorListAdapter(std::vector<std::string> *items) : items_(items) {}
|
||||
virtual size_t getCount() const { return items_->size(); }
|
||||
virtual void drawItem(int item, int x, int y, int w, int h, bool active) const;
|
||||
StringVectorListAdapter(std::vector<std::string> *items) : items_(items) {}
|
||||
virtual size_t getCount() const { return items_->size(); }
|
||||
virtual void drawItem(int item, int x, int y, int w, int h, bool active) const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> *items_;
|
||||
std::vector<std::string> *items_;
|
||||
};
|
||||
|
||||
struct UIListState {
|
||||
UIListState() : scrollY(0.0f), selected(-1) {}
|
||||
float scrollY;
|
||||
int selected;
|
||||
UIListState() : scrollY(0.0f), selected(-1) {}
|
||||
float scrollY;
|
||||
int selected;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +37,29 @@ inline uint32_t _rotr(uint32_t val, int shift) {
|
||||
return (val << shift) | (val >> (31 - shift));
|
||||
}
|
||||
|
||||
/*
|
||||
template <int SZ>
|
||||
class BitArray {
|
||||
public:
|
||||
BitArray() {
|
||||
memset(data, 0, sizeof(data));
|
||||
}
|
||||
|
||||
BitArray And(const BitArray &other) {
|
||||
BitArray<SZ> retVal;
|
||||
for (int i = 0; i < DATACOUNT; i++) {
|
||||
retVal.data[i] = data[i] & other.data[i];
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 data[(SZ + 31) / 32];
|
||||
enum {
|
||||
DATACOUNT = (SZ + 31) / 32;
|
||||
};
|
||||
};
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user