commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
440
include/modules/archive/archive.cpp
Normal file
440
include/modules/archive/archive.cpp
Normal file
@ -0,0 +1,440 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <cstring>
|
||||
#include "zlib.h"
|
||||
#include "archive/archive.h"
|
||||
#include "metafile/nml.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "thread/mutex.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::NML;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#define __CorrectOffsetPadding \
|
||||
{\
|
||||
if (offset_padding)\
|
||||
{\
|
||||
size_t error = handle->Tell() % offset_padding;\
|
||||
if (error)\
|
||||
handle->Seek((long)(offset_padding - error));\
|
||||
}\
|
||||
}
|
||||
bool ArchiveIndex::Load(const char *uri)
|
||||
{
|
||||
index.Clear();
|
||||
|
||||
__LOG_V__ << "Loading archive index '" << uri << "'...\n";
|
||||
|
||||
File file;
|
||||
if (!Parser::Load(uri, file))
|
||||
return false;
|
||||
|
||||
// Grab index tag.
|
||||
Tag *index_tag = file.GetTag("Index;");
|
||||
if (!index_tag)
|
||||
__ERR__(__LOG_E__ << "No archive index tag found in '" << uri << "'.\n", false)
|
||||
|
||||
// Pool for entries.
|
||||
NMLTagForeach(t, *index_tag)
|
||||
if (t->name == "Entry")
|
||||
{
|
||||
Tag *id_tag = t->GetTypedTag("ID;", Variant::VariantString),
|
||||
*compressed_tag = t->GetTypedTag("CompLen", Variant::VariantInteger),
|
||||
*length_tag = t->GetTypedTag("Len", Variant::VariantInteger),
|
||||
*method_tag = t->GetTypedTag("Method", Variant::VariantString),
|
||||
*offset_tag = t->GetTypedTag("Offset", Variant::VariantInteger);
|
||||
|
||||
if (id_tag && compressed_tag && length_tag && method_tag)
|
||||
{
|
||||
// Import the entry.
|
||||
if (ArchiveEntry *entry = new ArchiveEntry)
|
||||
{
|
||||
entry->path = id_tag->GetString();
|
||||
entry->length = length_tag->GetInteger();
|
||||
entry->compressed_length = compressed_tag->GetInteger();
|
||||
entry->offset = offset_tag->GetInteger();
|
||||
|
||||
String method(method_tag->GetString());
|
||||
|
||||
if (method == "Raw")
|
||||
entry->method = ArchiveEntry::MethodRaw;
|
||||
else if (method == "Zlib")
|
||||
entry->method = ArchiveEntry::MethodZLibCompress;
|
||||
|
||||
index.Add(entry);
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate new archive index entry.\n";
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Incomplete index entry.\n";
|
||||
}
|
||||
else
|
||||
__LOG_W__ << "Unexpected tag <" << t->name << "> in <Index>.\n";
|
||||
|
||||
__LOG_V__ << "Done, found " << index.GetCount() << " entries.\n";
|
||||
return true;
|
||||
}
|
||||
bool ArchiveIndex::Save(const char *uri)
|
||||
{
|
||||
File file;
|
||||
Tag *index_tag = file.AddRoot("Index");
|
||||
|
||||
ListForeachPtr(ArchiveEntry *, entry, index)
|
||||
{
|
||||
// Create entry.
|
||||
Tag *entry_tag = index_tag->AddChild("Entry");
|
||||
|
||||
entry_tag->AddChild("ID", entry->path.c_str());
|
||||
entry_tag->AddChild("CompLen", (int)entry->compressed_length);
|
||||
entry_tag->AddChild("Len", (int)entry->length);
|
||||
entry_tag->AddChild("Offset", (int)entry->offset);
|
||||
|
||||
switch (entry->method)
|
||||
{
|
||||
case ArchiveEntry::MethodRaw:
|
||||
entry_tag->AddChild("Method", "Raw");
|
||||
break;
|
||||
|
||||
case ArchiveEntry::MethodZLibCompress:
|
||||
entry_tag->AddChild("Method", "Zlib");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Parser::Save(uri, file);
|
||||
}
|
||||
ArchiveEntry *ArchiveIndex::FindEntry(const char *alias) const
|
||||
{
|
||||
ListForeachPtr(ArchiveEntry *, e, index)
|
||||
if (e->path == alias)
|
||||
return e;
|
||||
return NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Archive::LoadIndex(const char *uri)
|
||||
{ return index.Load(uri); }
|
||||
bool Archive::SaveIndex(const char *uri)
|
||||
{ return index.Save(uri); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Archive::OpenRead(const char *uri, const char *idx)
|
||||
{
|
||||
Close();
|
||||
if (!uri)
|
||||
__ERR__(__LOG_E__ << "No archive to open.\n", false)
|
||||
|
||||
if (!(handle = Platform::Get().io->Open(uri)))
|
||||
__ERR__(__LOG_E__ << "Failed to open archive '" << uri << "'.\n", false)
|
||||
|
||||
// Check archive header.
|
||||
__CorrectOffsetPadding
|
||||
|
||||
uint magic_word = handle->Read <uint> ();
|
||||
|
||||
if (magic_word == 0x4E415244) // 'NARD' (padding support).
|
||||
{
|
||||
__CorrectOffsetPadding
|
||||
offset_padding = handle->Read <int> ();
|
||||
__CorrectOffsetPadding
|
||||
size_padding = handle->Read <int> ();
|
||||
revision = EnhancedLegacy;
|
||||
}
|
||||
else if (magic_word == 0x4E415243) // 'NARC' backward compatibility.
|
||||
{
|
||||
offset_padding = 0;
|
||||
size_padding = 0;
|
||||
revision = Legacy;
|
||||
}
|
||||
else
|
||||
{
|
||||
__LOG_E__ << "Invalid archive type '" << uri << "'.\n";
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Open or create index if none provided.
|
||||
if (!idx)
|
||||
{
|
||||
size_t alen = handle->GetSize();
|
||||
|
||||
if (verbose)
|
||||
__LOG__ << "No index provided, please wait while scanning archive...\n";
|
||||
|
||||
while (handle->Tell() < alen)
|
||||
{
|
||||
// Fetch alias.
|
||||
char tmp[512];
|
||||
__CorrectOffsetPadding
|
||||
uint tsz = handle->Read <uint> ();
|
||||
|
||||
if (tsz > 511)
|
||||
break;
|
||||
|
||||
else
|
||||
{
|
||||
handle->Read((void *)tmp, tsz);
|
||||
tmp[tsz] = 0;
|
||||
}
|
||||
|
||||
// Attributes.
|
||||
__CorrectOffsetPadding
|
||||
char cmp = handle->Read <uchar> () & 1;
|
||||
__CorrectOffsetPadding
|
||||
uint len = handle->Read <uint> (), clen = len;
|
||||
if (cmp)
|
||||
{
|
||||
__CorrectOffsetPadding
|
||||
clen = handle->Read <uint> ();
|
||||
}
|
||||
|
||||
// Store in index.
|
||||
if (ArchiveEntry *entry = new ArchiveEntry)
|
||||
{
|
||||
entry->path = tmp;
|
||||
entry->method = cmp;
|
||||
entry->length = len;
|
||||
entry->compressed_length = clen;
|
||||
entry->offset = handle->Tell();
|
||||
index.index.Add(entry);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
__LOG__ << "New entry: '" << entry->path << "'\n";
|
||||
__LOG__ << "[method = " << entry->method << ", len = " << (uint)entry->length << ", clen = " << (uint)entry->compressed_length << ", offset = " << (uint)entry->offset << "].\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Could not allocate new index entry.\n";
|
||||
|
||||
handle->Seek(clen);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
__LOG__ << "Done, index table built.\n\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadIndex(idx);
|
||||
|
||||
if (verbose)
|
||||
ListForeachPtr(ArchiveEntry *, entry, index.index)
|
||||
{
|
||||
__LOG__ << "New entry: '" << entry->path << "'\n";
|
||||
__LOG__ << "[method = " << entry->method << ", len = " << (uint)entry->length << ", clen = " << (uint)entry->compressed_length << ", offset = " << (uint)entry->offset << "].\n";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Archive::CreateNew(const char *uri)
|
||||
{
|
||||
Close();
|
||||
|
||||
if (!(handle = Platform::Get().io->Open(uri, IO::ModeWrite)))
|
||||
__ERR__(__LOG_E__ << "Failed to open '" << uri << "' as output archive.\n", false)
|
||||
|
||||
// Output header.
|
||||
__CorrectOffsetPadding
|
||||
handle->Write <uint> (0x4E415244); // 'NARD'
|
||||
__CorrectOffsetPadding
|
||||
handle->Write <int> (offset_padding);
|
||||
__CorrectOffsetPadding
|
||||
handle->Write <int> (size_padding);
|
||||
|
||||
append_mode = true;
|
||||
return true;
|
||||
}
|
||||
void Archive::Close()
|
||||
{
|
||||
if (append_mode)
|
||||
{
|
||||
// EOF marker.
|
||||
handle->Write <uint> (0xffffffff);
|
||||
|
||||
// Size padding.
|
||||
size_t size = handle->Tell();
|
||||
size_t pad_count = size_padding ? size_padding - size % size_padding : 0;
|
||||
|
||||
for (size_t n = 0; n < pad_count; ++n)
|
||||
handle->Write <uchar> (0xff); // End of archive marker (entry id length > 512).
|
||||
}
|
||||
|
||||
// Close archive.
|
||||
handle = NULL;
|
||||
index.index.Clear();
|
||||
|
||||
if (append_mode)
|
||||
__LOG__ << "Archive complete, closing.\n";
|
||||
append_mode = false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Archive::FileRead(const char *path, void *out)
|
||||
{
|
||||
if (append_mode)
|
||||
__ERR__(__LOG_E__ << "Cannot load '" << path << "' (r/w mode error).\n", false)
|
||||
|
||||
ArchiveEntry *entry = Exists(path);
|
||||
if (!entry)
|
||||
__ERR__(__LOG_E__ << "Could not find '" << path << "'.\n", false)
|
||||
|
||||
Threading::MutexLock lock(access_mutex);
|
||||
|
||||
size_t h_cursor = handle->Tell();
|
||||
|
||||
switch (entry->method)
|
||||
{
|
||||
case ArchiveEntry::MethodRaw:
|
||||
handle->Seek(entry->offset, IO::Base::SeekStart); // Note: Should be padded to the right offset already.
|
||||
if (handle->Read(out, entry->length) != entry->length)
|
||||
__LOG_E__ << "Failed to load raw source.\n";
|
||||
break;
|
||||
|
||||
case ArchiveEntry::MethodZLibCompress:
|
||||
{
|
||||
handle->Seek(entry->offset, IO::Base::SeekStart); // Note: Should be padded to the right offset already.
|
||||
|
||||
Array <char> cp((uint)(entry->compressed_length + 16));
|
||||
if (!cp)
|
||||
__ERR__(__LOG_E__ << "Failed to allocated compressed memory support.\n", false)
|
||||
|
||||
if (handle->Read((void *)cp, entry->compressed_length) != entry->compressed_length)
|
||||
__ERR__(__LOG_E__ << "Failed to load compressed source.\n", false)
|
||||
|
||||
uLong out_len = (uLong)entry->length;
|
||||
uncompress((Bytef *)out, &out_len, (Bytef *)&cp[0], (uLong)entry->compressed_length);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
handle->Seek(h_cursor, IO::Base::SeekStart);
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
ArchiveEntry *Archive::MemoryBlockWrite(const char *alias, const void *in, size_t len, int level)
|
||||
{
|
||||
if (!append_mode || !len)
|
||||
__ERR__(__LOG_E__ << "Cannot write '" << alias << "' (r/w mode error).\n", NULL)
|
||||
|
||||
Threading::MutexLock lock(access_mutex);
|
||||
|
||||
// Ensure alias uniqueness.
|
||||
if (ArchiveEntry *e = index.FindEntry(alias))
|
||||
return e;
|
||||
|
||||
// Sync index.
|
||||
ArchiveEntry *entry = new ArchiveEntry;
|
||||
if (!entry)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate new index entry.\n", NULL)
|
||||
entry->path = alias;
|
||||
index.index.Add(entry);
|
||||
|
||||
// Compress and add to archive.
|
||||
Array <char> out;
|
||||
size_t clen;
|
||||
|
||||
// Output alias.
|
||||
__CorrectOffsetPadding
|
||||
handle->Write <uint> (std::strlen(alias));
|
||||
__CorrectOffsetPadding
|
||||
handle->Write((const void *)alias, std::strlen(alias));
|
||||
if (verbose)
|
||||
__LOG_H__ << "Adding '" << alias << "' to archive...\n";
|
||||
|
||||
// Output data, ZLIB needs destination to be at least source * 100.1% + 12 bytes.
|
||||
bool add_raw = true;
|
||||
|
||||
if (level >= 0)
|
||||
{
|
||||
clen = len + (len / 1000 + 1) + 12;
|
||||
|
||||
if (out.Allocate((uint)clen) && (compress2((Bytef *)&out[0], (uLongf *)&clen, (const Bytef *)in, (uLong)len, level) == Z_OK))
|
||||
{
|
||||
// @TODO compression method as a bit flag here.
|
||||
__CorrectOffsetPadding
|
||||
handle->Write <uchar> (1);
|
||||
__CorrectOffsetPadding
|
||||
handle->Write <uint> (len);
|
||||
__CorrectOffsetPadding
|
||||
handle->Write <uint> (clen);
|
||||
|
||||
// Write compressed block.
|
||||
__CorrectOffsetPadding
|
||||
entry->method = ArchiveEntry::MethodZLibCompress;
|
||||
entry->offset = handle->Tell();
|
||||
entry->length = len;
|
||||
entry->compressed_length = clen;
|
||||
|
||||
if (verbose)
|
||||
__LOG__ << "Was " << (uint)(len / 1000) << " KB, is now " << (uint)(clen / 1000) << " KB (" << (uint)(clen * 100 / len) <<"%).\n";
|
||||
|
||||
handle->Write((const void *)out, clen);
|
||||
add_raw = false;
|
||||
}
|
||||
else
|
||||
if (verbose)
|
||||
__LOG__ << "No compression achieved for '" << alias << "', adding uncompressed.\n";
|
||||
}
|
||||
|
||||
if (add_raw)
|
||||
{
|
||||
__CorrectOffsetPadding
|
||||
handle->Write <uchar> (0);
|
||||
__CorrectOffsetPadding
|
||||
handle->Write <uint> (len);
|
||||
|
||||
// Write raw block.
|
||||
__CorrectOffsetPadding
|
||||
|
||||
entry->method = ArchiveEntry::MethodRaw;
|
||||
entry->offset = handle->Tell();
|
||||
entry->length = len;
|
||||
entry->compressed_length = 0;
|
||||
|
||||
handle->Write((const void *)in, len);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
ArchiveEntry *Archive::FileWrite(const char *path, const char *alias, int level)
|
||||
{
|
||||
Array <char> data;
|
||||
if (!Platform::Get().io->FileLoad(path, data))
|
||||
return NULL;
|
||||
return MemoryBlockWrite(alias ? alias : path, &data[0], data.GetSize(), level);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Archive::Archive()
|
||||
{
|
||||
append_mode = false;
|
||||
offset_padding = 0;
|
||||
size_padding = 0;
|
||||
|
||||
access_mutex = new Threading::Mutex;
|
||||
}
|
||||
Archive::~Archive()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
190
include/modules/audio_stream_ogg/audio_stream_ogg.cpp
Normal file
190
include/modules/audio_stream_ogg/audio_stream_ogg.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "audio_stream_ogg/audio_stream_ogg.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
#include "stb_vorbis.c"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::IO;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool AudioStreamOGG::Seek(int t_ms)
|
||||
{
|
||||
/// Rewind the stream and seek to the correct frame.
|
||||
int target = (vf->sample_rate * t_ms) / 1000;
|
||||
|
||||
// Logic is broken when seeking below the first packet.
|
||||
if (target < 1024)
|
||||
{
|
||||
h->Rewind();
|
||||
byte_left = 0;
|
||||
|
||||
stb_vorbis_flush_pushdata(vf);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO compute seek point and sample to skip.
|
||||
int lo = 0, hi = h->GetSize();
|
||||
|
||||
forever
|
||||
{
|
||||
// Determine seek point.
|
||||
int mid = (lo + hi) / 2;
|
||||
|
||||
// Seek and reload push buffer.
|
||||
h->Seek(mid, Base::SeekStart);
|
||||
RefillBuffer();
|
||||
|
||||
stb_vorbis_flush_pushdata(vf);
|
||||
|
||||
int ns = 0, ch = 0, cs = 0;
|
||||
float **fo = NULL;
|
||||
|
||||
forever
|
||||
{
|
||||
ConsumeBuffer(stb_vorbis_decode_frame_pushdata(vf, (uchar *)buffer.c_ptr(), byte_left, &ch, &fo, &ns));
|
||||
|
||||
if (ns) // Samples are coming in.
|
||||
{
|
||||
cs = stb_vorbis_get_sample_offset(vf);
|
||||
if (cs != -1) // Sample located.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if target sample is within reach.
|
||||
if ((cs > (target - 24000)) && (cs <= target))
|
||||
forever
|
||||
{
|
||||
RefillBuffer();
|
||||
ConsumeBuffer(stb_vorbis_decode_frame_pushdata(vf, (uchar *)buffer.c_ptr(), byte_left, &ch, &fo, &ns));
|
||||
|
||||
int skip = target - cs;
|
||||
if ((cs != -1) && (skip < ns))
|
||||
{
|
||||
seek_correction = skip;
|
||||
return true;
|
||||
}
|
||||
cs = stb_vorbis_get_sample_offset(vf);
|
||||
}
|
||||
|
||||
// Refine approximation.
|
||||
if (cs > target)
|
||||
hi = mid;
|
||||
else
|
||||
lo = mid;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
size_t AudioStreamOGG::GetPCMBufferSize() const
|
||||
{ return vorbis_info.max_frame_size * format.channels * 2 * 2; }
|
||||
size_t AudioStreamOGG::GetPCM(void *pcm)
|
||||
{
|
||||
int ns, ch;
|
||||
float **fo = NULL;
|
||||
|
||||
RefillBuffer();
|
||||
ConsumeBuffer(stb_vorbis_decode_frame_pushdata(vf, (uchar *)buffer.c_ptr(), byte_left, &ch, &fo, &ns));
|
||||
|
||||
if (vf->error != VORBIS__no_error)
|
||||
return 0;
|
||||
|
||||
if (seek_correction)
|
||||
{
|
||||
for (int n = 0; n < ch; ++n)
|
||||
fo[n] += seek_correction;
|
||||
ns -= seek_correction;
|
||||
seek_correction = 0;
|
||||
}
|
||||
if (ns < 0)
|
||||
ns = 0;
|
||||
|
||||
convert_channels_short_interleaved(ch, (short *)pcm, ch, fo, 0, ns); // size = ns * 2 * format.channels
|
||||
return ns * 2 * format.channels;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
size_t AudioStreamOGG::RefillBuffer()
|
||||
{
|
||||
size_t request_size = buffer.GetSize() - byte_left;
|
||||
size_t read = h->Read(&buffer[(int)byte_left], request_size);
|
||||
byte_left += read;
|
||||
return read;
|
||||
}
|
||||
void AudioStreamOGG::ConsumeBuffer(size_t size)
|
||||
{
|
||||
memmove(buffer, &buffer[(int)size], byte_left - size);
|
||||
byte_left -= size;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool AudioStreamOGG::IsEOF() const
|
||||
{
|
||||
if (byte_left > 0)
|
||||
return false;
|
||||
if (h->IsEOF())
|
||||
return true;
|
||||
return vf ? asbool(vf->eof) : false;
|
||||
}
|
||||
bool AudioStreamOGG::Open(const char *uri)
|
||||
{
|
||||
h = Platform::Get().io->Open(uri);
|
||||
if (!h)
|
||||
return false;
|
||||
|
||||
if (!buffer.Allocate(16384))
|
||||
return false;
|
||||
|
||||
RefillBuffer();
|
||||
vf = stb_vorbis_open_pushdata((uchar *)buffer.c_ptr(), byte_left, &consumed, &err, NULL);
|
||||
if (!vf)
|
||||
{
|
||||
h = NULL;
|
||||
return false;
|
||||
}
|
||||
ConsumeBuffer(consumed);
|
||||
|
||||
vorbis_info = stb_vorbis_get_info(vf);
|
||||
seek_correction = 0;
|
||||
|
||||
format.channels = vorbis_info.channels;
|
||||
format.resolution = 16;
|
||||
format.frequency = vorbis_info.sample_rate;
|
||||
|
||||
__LOG_H__ << "Vorbis stream '" << uri << "' - " << vorbis_info.sample_rate << "hz 16bit " << vorbis_info.channels << " channel(s).\n";
|
||||
__LOG__ << " Max frame size = " << vorbis_info.max_frame_size << "\n";
|
||||
return true;
|
||||
}
|
||||
void AudioStreamOGG::Close()
|
||||
{
|
||||
if (vf)
|
||||
stb_vorbis_close(vf);
|
||||
vf = NULL;
|
||||
|
||||
__LOG_H__ << "Vorbis stream closed.\n";
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
AudioStreamOGG::AudioStreamOGG()
|
||||
{
|
||||
vf = NULL;
|
||||
seek_correction = 0;
|
||||
byte_left = 0;
|
||||
}
|
||||
AudioStreamOGG::~AudioStreamOGG()
|
||||
{ Close(); }
|
||||
//------------------------------------------------------------------------------
|
||||
@ -0,0 +1,21 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "audio_stream_ogg/audio_stream_ogg_factory.h"
|
||||
#include "audio_stream_ogg/audio_stream_ogg.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
IAudioStream *OGGStreamFactory::Open(const char *path)
|
||||
{
|
||||
AutoPtr <AudioStreamOGG> stream(new AudioStreamOGG);
|
||||
if (!stream->Open(path))
|
||||
return NULL;
|
||||
return stream.Detach();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
136
include/modules/debug_enet/network_debugger.cpp
Normal file
136
include/modules/debug_enet/network_debugger.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "network_debugger.h"
|
||||
#include "network_debugger_thread.h"
|
||||
#include "metafile/nml.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetworkDebugger::OnControllerPacketReceived(const Array <char> &data)
|
||||
{
|
||||
using namespace NML;
|
||||
|
||||
Tag tag;
|
||||
Parser::ParseTag(tag, data.Start(), data.End());
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
if (tag.name == "Start")
|
||||
start_signal = true;
|
||||
else if (tag.name == "StepInto")
|
||||
debugger->StepInto();
|
||||
else if (tag.name == "StepOver")
|
||||
debugger->Step();
|
||||
else if (tag.name == "StepOut")
|
||||
debugger->StepOut();
|
||||
else if (tag.name == "Resume")
|
||||
debugger->Resume();
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
else if (tag.name == "SetDebugStackFrame")
|
||||
debugger->SetDebugStackFrame(tag.GetInteger());
|
||||
else if (tag.name == "SetTopDebugStackFrame")
|
||||
debugger->SetDebugStackFrame(-1);
|
||||
|
||||
else if (tag.name == "RequestDebugStackFrameSource")
|
||||
{
|
||||
const char *source; int line;
|
||||
debugger->GetStackFrameSource(source, line);
|
||||
|
||||
if (source)
|
||||
BroadcastNetworkCommand(String::Format("<SetDebugSource=<Source=\"%s\"><Line=%d>>", source, line));
|
||||
}
|
||||
else if (tag.name == "RequestDebugCallStack")
|
||||
BroadcastNetworkCommand(GetCallstack());
|
||||
else if (tag.name == "RequestDebugStackFrameLocals")
|
||||
BroadcastNetworkCommand(GetDebugStackFrameLocals());
|
||||
else if (tag.name == "SetBreakpoints")
|
||||
debugger->SetBreakpoints(tag);
|
||||
//----------------------------------------------------------------------
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
String NetworkDebugger::GetPeerAddress()
|
||||
{
|
||||
ASync::Future <String> address;
|
||||
thread->async.QueueMemberCall(address, thread, &NetworkDebuggerThread::GetControllerAddress);
|
||||
return address.Get();
|
||||
}
|
||||
bool NetworkDebugger::IsConnected() const
|
||||
{ return thread->IsConnected(); }
|
||||
void NetworkDebugger::Stop()
|
||||
{ thread->Stop(); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetworkDebugger::BroadcastNetworkCommand(const String &cmd)
|
||||
{
|
||||
// Queue an asynchronous call to the controller thread.
|
||||
thread->async.QueueMemberCall(thread, &NetworkDebuggerThread::SendToController, cmd);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetworkDebugger::OnSuspendExecution(const char *source, int line)
|
||||
{
|
||||
// Set callstack, stack frame locals and source.
|
||||
BroadcastNetworkCommand(GetCallstack());
|
||||
BroadcastNetworkCommand(debugger->GetStackFrameLocals());
|
||||
BroadcastNetworkCommand(String::Format("<SetDebugSource=<Source=\"%s\"><Line=%d>>", source, line));
|
||||
}
|
||||
bool NetworkDebugger::OnUpdateSuspendedExecution()
|
||||
{
|
||||
async.Execute(); // [EJ] execute calls pushed by the debug thread to us so that we may receive new packets
|
||||
return thread->IsConnected();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetworkDebugger::OnFatalError(const char *reason)
|
||||
{
|
||||
BroadcastNetworkCommand(String::Format("<VMKill=<Description=\"%s\">>", reason));
|
||||
}
|
||||
void NetworkDebugger::OnCompilerError(const char *error, const char *source, int line)
|
||||
{
|
||||
// Make sure the error location is displayed prior to the VM kill event being received.
|
||||
BroadcastNetworkCommand(String::Format("<SetDebugSource=<Source=\"%s\"><Line=%d>>", source, line));
|
||||
BroadcastNetworkCommand(String::Format("<VMKill=<Description=\"%s\">>", error));
|
||||
}
|
||||
void NetworkDebugger::OnRuntimeException(const char *error)
|
||||
{
|
||||
BroadcastNetworkCommand(String::Format("<VMException=<Description=\"%s\">>", error));
|
||||
|
||||
/*
|
||||
...then suspend all execution beside the server inspection communication
|
||||
channels. The VM along with the executing program will die when this
|
||||
function returns.
|
||||
*/
|
||||
while ((vm->GetState() == IVM::StateExceptionThrown) && thread->IsConnected())
|
||||
{
|
||||
async.Execute();
|
||||
Threading::Thread::Switch();
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NetworkDebugger::NetworkDebugger(IVM *vm, IDebugger *debugger, const char *address, int port) : IDebuggerProfiler(vm, debugger)
|
||||
{
|
||||
start_signal = false;
|
||||
|
||||
thread = new NetworkDebuggerThread(*this, address, port);
|
||||
thread->Start();
|
||||
}
|
||||
NetworkDebugger::~NetworkDebugger()
|
||||
{
|
||||
_safe_delete(thread);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
167
include/modules/debug_enet/network_debugger_thread.cpp
Normal file
167
include/modules/debug_enet/network_debugger_thread.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "network_debugger_thread.h"
|
||||
#include "network_debugger.h"
|
||||
#include "core/engine.h"
|
||||
#include "metafile/nml.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetworkDebuggerThread::OnPacketReceived(void *peer, const void *data, size_t size)
|
||||
{
|
||||
using namespace NML;
|
||||
|
||||
Tag tag;
|
||||
Parser::ParseTag(tag, (char *)data, (char *)data + size);
|
||||
|
||||
if (ctl_peer == NULL)
|
||||
{
|
||||
if (tag.name == "HelloMonitor")
|
||||
{
|
||||
Tag *client_version = tag.GetTag("Version;");
|
||||
|
||||
if (client_version->GetInteger() == 1)
|
||||
{
|
||||
ctl_peer = peer;
|
||||
SendString(peer, String::Format("<Welcome=<Platform=\"%s\"><Version=\"%s\">>", Platform::Get().GetName().c_str(), Core::Version));
|
||||
|
||||
ctl.async.QueueMemberCall(&ctl, &NetworkDebugger::OnControllerConnected);
|
||||
|
||||
connected.Set(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
Disconnect(peer);
|
||||
}
|
||||
else if (ctl_peer == peer)
|
||||
ctl.async.QueueMemberCall(&ctl, &NetworkDebugger::OnControllerPacketReceived, Array <char> ((uint)size, (const char *)data));
|
||||
else
|
||||
Disconnect(peer);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetworkDebuggerThread::OnPeerConnection(void *peer)
|
||||
{
|
||||
if (ctl_peer == NULL)
|
||||
{
|
||||
SetPeerTimeout(peer, TimeoutVeryLong);
|
||||
SendString(peer, "<Ident>");
|
||||
}
|
||||
else
|
||||
Disconnect(peer);
|
||||
}
|
||||
void NetworkDebuggerThread::OnConnectionClosed(void *peer)
|
||||
{
|
||||
if (peer == ctl_peer)
|
||||
{
|
||||
ctl.async.QueueMemberCall(&ctl, &NetworkDebugger::OnControllerDisconnected);
|
||||
ctl.async.QueueMemberCall(&ctl, &NetworkDebugger::Kill);
|
||||
ctl_peer = NULL;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetworkDebuggerThread::SendToController(const GS::String &p)
|
||||
{
|
||||
if (ctl_peer)
|
||||
SendString(ctl_peer, p.c_str());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool NetworkDebuggerThread::OpenServer(const char *address, int port)
|
||||
{
|
||||
if (!Network::Enet::OpenServer(address, port))
|
||||
return false;
|
||||
|
||||
String host_address;
|
||||
GetHostAddress(host_address);
|
||||
ctl.async.QueueMemberCall(&ctl, &NetworkDebugger::OnNetworkReady, host_address, port);
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
GS::String NetworkDebuggerThread::GetControllerAddress()
|
||||
{
|
||||
String address;
|
||||
if (ctl_peer)
|
||||
GetPeerAddress(ctl_peer, address);
|
||||
return address;
|
||||
}
|
||||
void NetworkDebuggerThread::DisconnectController()
|
||||
{
|
||||
if (ctl_peer)
|
||||
{
|
||||
SendString(ctl_peer, "<EndSession>");
|
||||
connected.Set(0);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetworkDebuggerThread::Execute()
|
||||
{
|
||||
Thread::SetName("NetworkDebuggerThread");
|
||||
|
||||
if (!OpenServer(address, port))
|
||||
return;
|
||||
|
||||
for (state.Set(StateWaitingController); state.Get() != StateStop; )
|
||||
{
|
||||
switch (state.Get())
|
||||
{
|
||||
case StateWaitingController: if (ctl_peer) state.Set(StateControllerConnected); break;
|
||||
case StateControllerConnected: if (ctl_peer == NULL) state.Set(StateStop); break; // if controller lost, stop debugger
|
||||
}
|
||||
|
||||
UpdateHost();
|
||||
|
||||
while (async.Execute());
|
||||
|
||||
Platform::Get().Sleep(1);
|
||||
}
|
||||
|
||||
DisconnectController();
|
||||
Close();
|
||||
|
||||
connected.Set(0);
|
||||
|
||||
state.Set(StateStopped);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetworkDebuggerThread::Stop()
|
||||
{
|
||||
if (state.Get() != StateStopped)
|
||||
{
|
||||
state.Set(StateStop);
|
||||
while (state.Get() != StateStopped); // spinlock
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NetworkDebuggerThread::NetworkDebuggerThread(NetworkDebugger &h, const char *a, int p) : ctl(h)
|
||||
{
|
||||
address = a;
|
||||
port = p;
|
||||
|
||||
ctl_peer = NULL;
|
||||
}
|
||||
NetworkDebuggerThread::~NetworkDebuggerThread()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
155
include/modules/font_freetype/ft2_font.cpp
Normal file
155
include/modules/font_freetype/ft2_font.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "font_freetype/ft2_font.h"
|
||||
#include "picture/pict.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int Freetype2Font::GetAdvance() const
|
||||
{ return face ? face->glyph->advance.x : 0; }
|
||||
bool Freetype2Font::SetPixelSize(int size)
|
||||
{
|
||||
if (face == 0)
|
||||
return false;
|
||||
|
||||
FT_Set_Pixel_Sizes(face, 0, size);
|
||||
return true;
|
||||
}
|
||||
int Freetype2Font::GetHeight() const
|
||||
{ return face ? face->size->metrics.height : 0; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Freetype2Font::HasKerning() const
|
||||
{ return has_kerning; }
|
||||
int Freetype2Font::GetKerning(uint previous_codepoint, uint codepoint) const
|
||||
{
|
||||
if (face == 0)
|
||||
return 0;
|
||||
|
||||
FT_Vector delta;
|
||||
FT_UInt previous_glyph_index = FT_Get_Char_Index(face, previous_codepoint), glyph_index = FT_Get_Char_Index(face, codepoint);
|
||||
return FT_Get_Kerning(face, previous_glyph_index, glyph_index, FT_KERNING_DEFAULT, &delta) == 0 ? delta.x : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Freetype2Font::LoadGlyph(uint codepoint, bool for_render)
|
||||
{
|
||||
FT_UInt index = FT_Get_Char_Index(face, codepoint);
|
||||
return FT_Load_Glyph(face, index, for_render ? FT_LOAD_RENDER : FT_LOAD_DEFAULT) == 0;
|
||||
}
|
||||
bool Freetype2Font::RenderCurrentGlyph(Picture &picture, const iPoint &position, const iRect &clip, const Color &color)
|
||||
{
|
||||
if (face == 0)
|
||||
return false;
|
||||
|
||||
if (position.x >= clip.ex)
|
||||
return true;
|
||||
|
||||
int r_offset = picture.GetPixelFormat().rshift / 8, g_offset = picture.GetPixelFormat().gshift / 8, b_offset = picture.GetPixelFormat().bshift / 8, a_offset = picture.GetPixelFormat().ashift / 8;
|
||||
int ir = int(color.x), ig = int(color.y), ib = int(color.z), ia = int(color.w);
|
||||
|
||||
FT_GlyphSlot slot = face->glyph;
|
||||
FT_Bitmap *bmp = &slot->bitmap;
|
||||
unsigned char *bpt = bmp->buffer;
|
||||
|
||||
if (!bpt)
|
||||
return false;
|
||||
|
||||
int pos_x = position.x + slot->bitmap_left;
|
||||
int pos_y = position.y - slot->bitmap_top ;
|
||||
|
||||
unsigned char *opt = picture.GetData() + (pos_y * picture.GetWidth() + pos_x) * 4;
|
||||
|
||||
for (int y = 0; y < bmp->rows; ++y)
|
||||
{
|
||||
if ((pos_y >= clip.sy) && (pos_y < clip.ey))
|
||||
{
|
||||
uchar *spt = opt;
|
||||
for (int x = 0; x < bmp->width; ++x)
|
||||
{
|
||||
int tx = pos_x + x;
|
||||
|
||||
if ((tx >= clip.sx) && (tx < clip.ex))
|
||||
{
|
||||
#if 1
|
||||
uchar alpha = (uchar)((bpt[x] * ia) >> 8);
|
||||
uchar a_blend = Picture::AlphaCompositeAlpha(spt[a_offset], alpha);
|
||||
|
||||
spt[r_offset] = Picture::AlphaCompositeColor(spt[r_offset], ir, spt[a_offset], alpha, a_blend);
|
||||
spt[g_offset] = Picture::AlphaCompositeColor(spt[g_offset], ig, spt[a_offset], alpha, a_blend);
|
||||
spt[b_offset] = Picture::AlphaCompositeColor(spt[b_offset], ib, spt[a_offset], alpha, a_blend);
|
||||
spt[a_offset] = a_blend;
|
||||
#else
|
||||
uchar alpha = (bpt[x] * (uchar)state.a) >> 8;
|
||||
spt[r_offset] = (uchar)state.r;
|
||||
spt[g_offset] = (uchar)state.g;
|
||||
spt[b_offset] = (uchar)state.b;
|
||||
spt[a_offset] = Types::Max(spt[a_offset], alpha);
|
||||
#endif
|
||||
}
|
||||
spt += 4;
|
||||
}
|
||||
}
|
||||
bpt += bmp->pitch;
|
||||
opt += picture.GetWidth() * 4;
|
||||
|
||||
pos_y++;
|
||||
if (pos_y >= (int)clip.ey)
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
iRect Freetype2Font::GetTextBoundRect(const char *text) const
|
||||
{
|
||||
FT_GlyphSlot slot = face->glyph;
|
||||
FT_UInt previous = 0;
|
||||
|
||||
iRect rc(0, 0, 0, 0);
|
||||
if (!text)
|
||||
return rc;
|
||||
|
||||
forever
|
||||
{
|
||||
char c = *text++;
|
||||
if (c == 0)
|
||||
break;
|
||||
if (c == '\n')
|
||||
continue;
|
||||
|
||||
FT_UInt glyph_index = FT_Get_Char_Index(face, c);
|
||||
|
||||
if (has_kerning && previous && glyph_index)
|
||||
{
|
||||
FT_Vector delta;
|
||||
FT_Get_Kerning(face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
|
||||
rc.ex += delta.x;
|
||||
}
|
||||
if (FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT))
|
||||
continue;
|
||||
|
||||
rc.ex += slot->advance.x;
|
||||
if (slot->metrics.height > rc.ey)
|
||||
rc.ey = slot->metrics.height;
|
||||
previous = glyph_index;
|
||||
}
|
||||
|
||||
rc.ex >>= 6;
|
||||
rc.ey >>= 6;
|
||||
return rc;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Freetype2Font::~Freetype2Font()
|
||||
{ FT_Done_Face(face); }
|
||||
42
include/modules/font_freetype/ft2_font_factory.cpp
Normal file
42
include/modules/font_freetype/ft2_font_factory.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "font_freetype/ft2_font_factory.h"
|
||||
#include "font_freetype/ft2_font.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
IFont *Freetype2FontFactory::LoadFont(const char *path)
|
||||
{
|
||||
__LOG_H__ << "Freetype2: Loading font '" << path << "'.\n";
|
||||
AutoPtr <Freetype2Font> font(new Freetype2Font);
|
||||
|
||||
if (font.IsNull())
|
||||
return NULL;
|
||||
|
||||
font->name = path;
|
||||
if (!Platform::Get().io->FileLoad(path, font->buffer))
|
||||
return NULL;
|
||||
|
||||
if (FT_New_Memory_Face(ft2, (const FT_Byte *)&font->buffer[0], font->buffer.GetSize(), 0, &font->face))
|
||||
__ERR__(__LOG_W__ << "Failed to open font file '" << path << "'.\n", NULL)
|
||||
|
||||
font->has_kerning = true; // FT_HAS_KERNING
|
||||
|
||||
return font.Detach();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Freetype2FontFactory::Freetype2FontFactory()
|
||||
{ FT_Init_FreeType(&ft2); }
|
||||
Freetype2FontFactory::~Freetype2FontFactory()
|
||||
{ FT_Done_FreeType(ft2); }
|
||||
//------------------------------------------------------------------------------
|
||||
102
include/modules/http_curl/http_curl.cpp
Normal file
102
include/modules/http_curl/http_curl.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "http_curl/http_curl.h"
|
||||
#include "async/async_call_queue_thread.h"
|
||||
#include "platform.h"
|
||||
|
||||
using namespace GS::Threading;
|
||||
using namespace GS::HTTP;
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace HTTP {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
class CurlThread : public ASyncCallQueueThread
|
||||
{
|
||||
Curl *icurl;
|
||||
void *curl;
|
||||
|
||||
public:
|
||||
|
||||
void Execute()
|
||||
{
|
||||
curl = curl_easy_init();
|
||||
if (!curl)
|
||||
return;
|
||||
|
||||
ASyncCallQueueThread::Execute();
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
curl = NULL;
|
||||
}
|
||||
|
||||
static size_t WriteData(void *buffer, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
Array <char> *data = (Array <char> *)userp;
|
||||
|
||||
size_t offset = data->GetSize();
|
||||
size_t total_size = offset + size * nmemb;
|
||||
if (!data->Reallocate(total_size))
|
||||
return 0;
|
||||
|
||||
Memory::Copy(&data->c_ptr()[offset], buffer, size * nmemb);
|
||||
return size * nmemb;
|
||||
}
|
||||
void Post(int ticket_id, const String &url, const String &post)
|
||||
{
|
||||
Array <char> response;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteData);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
|
||||
|
||||
if (curl_easy_perform(curl) == 0)
|
||||
icurl->event_queue.QueueMemberCall(icurl, &Curl::OnRequestComplete, ticket_id, response);
|
||||
else
|
||||
icurl->event_queue.QueueMemberCall(icurl, &Curl::OnRequestError, ticket_id);
|
||||
}
|
||||
|
||||
CurlThread(Curl *c) : icurl(c), curl(0) {}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // HTTP
|
||||
} // GS
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int Curl::GetTicketId()
|
||||
{ return u_ticket_id++; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Curl::Update()
|
||||
{
|
||||
event_queue.ExecuteAll();
|
||||
}
|
||||
int Curl::Post(const char *url, const char *post)
|
||||
{
|
||||
int ticket_id = GetTicketId();
|
||||
curl_thread->QueueMemberCall(curl_thread, &CurlThread::Post, ticket_id, url, post);
|
||||
return ticket_id;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Curl::Curl() : u_ticket_id(0)
|
||||
{
|
||||
curl_thread = new CurlThread(this);
|
||||
curl_thread->Start();
|
||||
}
|
||||
Curl::~Curl()
|
||||
{
|
||||
curl_thread->Stop();
|
||||
_safe_delete(curl_thread);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
985
include/modules/import_fbx/import_fbx.cpp
Normal file
985
include/modules/import_fbx/import_fbx.cpp
Normal file
@ -0,0 +1,985 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "import_fbx/import_fbx.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/mcamera.h"
|
||||
#include "core/graphic_resource_factory.h"
|
||||
#include "core/geometry.h"
|
||||
#include "core/renderer.h"
|
||||
#include "metafile/nml_object.h"
|
||||
#include "picture/pict_io.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "platform.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static FbxAMatrix ConvertGlobalMatrix(const FbxAMatrix &m) {
|
||||
FbxAMatrix k_m;
|
||||
k_m.SetS(FbxVector4(-1, 1, 1));
|
||||
return m * k_m;
|
||||
}
|
||||
|
||||
static Matrix4 FBXMatrixToMatrix4(const FbxAMatrix &fbx_m) {
|
||||
Matrix4 matrix;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
for (int j = 0; j < 4; ++j)
|
||||
matrix.m[i][j] = (float) fbx_m[j][i];
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
FbxScene *FBXImporter::LoadNativeScene(const char *fbx_path) {
|
||||
// Create an IOSettings object
|
||||
FbxIOSettings *ios = FbxIOSettings::Create(sdk_manager, IOSROOT);
|
||||
|
||||
// set some IOSettings options
|
||||
ios->SetBoolProp(IMP_FBX_MATERIAL, true);
|
||||
ios->SetBoolProp(IMP_FBX_TEXTURE, true);
|
||||
ios->SetBoolProp(IMP_FBX_LINK, false);
|
||||
ios->SetBoolProp(IMP_FBX_SHAPE, false);
|
||||
ios->SetBoolProp(IMP_FBX_GOBO, false);
|
||||
ios->SetBoolProp(IMP_FBX_ANIMATION, true);
|
||||
ios->SetBoolProp(IMP_FBX_GLOBAL_SETTINGS, true);
|
||||
|
||||
// Create an empty scene
|
||||
FbxScene *fbx_scene = FbxScene::Create(sdk_manager, "");
|
||||
|
||||
// Create an importer.
|
||||
FBXImporter *fbx_importer = FBXImporter::Create(sdk_manager, "");
|
||||
|
||||
if (fbx_importer->Initialize(fbx_path, -1, ios) && fbx_importer->Import(fbx_scene)) {
|
||||
input_path = String(fbx_path).CutFileName();
|
||||
|
||||
// Convert to our axis system and scale.
|
||||
FbxAxisSystem axis_system(FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd, FbxAxisSystem::eRightHanded);
|
||||
axis_system.ConvertScene(fbx_scene);
|
||||
|
||||
const FbxSystemUnit::ConversionOptions options =
|
||||
{
|
||||
false, /* mConvertRrsNodes */
|
||||
true, /* mConvertAllLimits */
|
||||
true, /* mConvertClusters */
|
||||
true, /* mConvertLightIntensity */
|
||||
true, /* mConvertPhotometricLProperties */
|
||||
true /* mConvertCameraClipPlanes */
|
||||
};
|
||||
FbxSystemUnit unit_system(100.f / config->scale);
|
||||
unit_system.ConvertScene(fbx_scene, options);
|
||||
} else {
|
||||
fbx_scene->Destroy();
|
||||
fbx_scene = NULL;
|
||||
}
|
||||
|
||||
fbx_importer->Destroy();
|
||||
return fbx_scene;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//#define __DEBUG_EULER__
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void FBXImporter::ExportMotionChannel(FbxNode *pNode, FbxAnimCurve *pCurve, Motion *motion,
|
||||
MotionChannel::Type channel_type) {
|
||||
if (!pCurve)
|
||||
return;
|
||||
|
||||
MotionChannel *channel = motion->AddChannel(channel_type);
|
||||
if (!channel)
|
||||
return;
|
||||
|
||||
channel->AllocatePoint(pCurve->KeyGetCount());
|
||||
|
||||
for (int n = 0; n < pCurve->KeyGetCount(); ++n) {
|
||||
FbxTime time = pCurve->KeyGetTime(n);
|
||||
|
||||
CurvePoint *point = (CurvePoint *) channel->GetPoints()[n];
|
||||
point->t = Time::fromSec(float(time.GetSecondDouble()));
|
||||
point->v = pCurve->KeyGetValue(n);
|
||||
|
||||
switch (pCurve->KeyGetInterpolation(n)) {
|
||||
default:
|
||||
case FbxAnimCurveDef::eInterpolationLinear: point->shape = CurvePoint::Shape_Linear;
|
||||
break;
|
||||
case FbxAnimCurveDef::eInterpolationConstant: point->shape = CurvePoint::Shape_Step;
|
||||
break;
|
||||
case FbxAnimCurveDef::eInterpolationCubic: point->shape = CurvePoint::Shape_Hermite;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FBXImporter::BakeTransformation(FbxNode *pNode, MItem *item, Motion *motion) {
|
||||
motion->SetUseQuaternion(true);
|
||||
|
||||
// Allocate position/scale.
|
||||
#ifdef __DEBUG_EULER__
|
||||
motion->AddChannels(9);
|
||||
#else
|
||||
motion->AddChannels(6);
|
||||
#endif
|
||||
|
||||
motion->GetChannel(0)->type = MotionChannel::XPos;
|
||||
motion->GetChannel(1)->type = MotionChannel::YPos;
|
||||
motion->GetChannel(2)->type = MotionChannel::ZPos;
|
||||
motion->GetChannel(3)->type = MotionChannel::XScl;
|
||||
motion->GetChannel(4)->type = MotionChannel::YScl;
|
||||
motion->GetChannel(5)->type = MotionChannel::ZScl;
|
||||
|
||||
#ifdef __DEBUG_EULER__
|
||||
motion->GetChannel(6)->type = MotionChannel::XRot;
|
||||
motion->GetChannel(7)->type = MotionChannel::YRot;
|
||||
motion->GetChannel(8)->type = MotionChannel::ZRot;
|
||||
#endif
|
||||
|
||||
// Bake animation.
|
||||
FbxTime tStart = fbx_scene->GetEvaluator()->GetContext()->ReferenceStart.Get(),
|
||||
tEnd = fbx_scene->GetEvaluator()->GetContext()->ReferenceStop.Get();
|
||||
|
||||
FbxTime tStep;
|
||||
tStep.SetSecondDouble(1.0 / double(config->frame_per_second));
|
||||
|
||||
for (FbxTime t = tStart; t < (tEnd + tStep); t += tStep) // Make sure to include the last key.
|
||||
{
|
||||
Time ts = Time::fromSec(float(t.GetSecondDouble()));
|
||||
|
||||
Vector4 p, s;
|
||||
Matrix3 r;
|
||||
FbxAMatrix m;
|
||||
|
||||
int dummy = -1;
|
||||
FbxAMatrix node_global_transform = fbx_scene->GetEvaluator()->GetNodeGlobalTransformFast(pNode, dummy, t);
|
||||
dummy = -1;
|
||||
|
||||
if (pNode->GetParent()) {
|
||||
FbxAMatrix parent_global_transform = fbx_scene->GetEvaluator()->GetNodeGlobalTransformFast(
|
||||
pNode->GetParent(), dummy, t);
|
||||
dummy = -1;
|
||||
m = ConvertGlobalMatrix(parent_global_transform).Inverse() * ConvertGlobalMatrix(node_global_transform);
|
||||
} else
|
||||
m = ConvertGlobalMatrix(node_global_transform);
|
||||
|
||||
FBXMatrixToMatrix4(m).Decompose(&p, &s, &r);
|
||||
|
||||
motion->GetChannel(0)->Append(CurvePoint(ts, p.x));
|
||||
motion->GetChannel(1)->Append(CurvePoint(ts, p.y));
|
||||
motion->GetChannel(2)->Append(CurvePoint(ts, p.z));
|
||||
motion->GetChannel(3)->Append(CurvePoint(ts, s.x));
|
||||
motion->GetChannel(4)->Append(CurvePoint(ts, s.y));
|
||||
motion->GetChannel(5)->Append(CurvePoint(ts, s.z));
|
||||
|
||||
#ifdef __DEBUG_EULER__
|
||||
Vector4 e = r.AsEuler();
|
||||
motion->GetChannel(6)->Insert(CurvePoint(ts, e.x));
|
||||
motion->GetChannel(7)->Insert(CurvePoint(ts, e.y));
|
||||
motion->GetChannel(8)->Insert(CurvePoint(ts, e.z));
|
||||
#else
|
||||
Quaternion q = Quaternion::FromMatrix3(r);
|
||||
motion->GetQuaternion().Insert(QuaternionKey(ts, q));
|
||||
#endif
|
||||
}
|
||||
// motion->Optimize();
|
||||
}
|
||||
|
||||
void FBXImporter::ExportMotions(FbxNode *pNode, MItem *item) {
|
||||
if (config->import_animation == false)
|
||||
return;
|
||||
|
||||
for (int n = 0; n < fbx_scene->GetSrcObjectCount<FbxAnimStack>(); n++) {
|
||||
FbxAnimStack *anim_stack = FbxCast<FbxAnimStack>(fbx_scene->GetSrcObject<FbxAnimStack>(n));
|
||||
if (!anim_stack)
|
||||
continue;
|
||||
fbx_scene->GetEvaluator()->SetContext(anim_stack);
|
||||
|
||||
// Convert to motion.
|
||||
Motion *motion = new Motion;
|
||||
if (!motion)
|
||||
continue;
|
||||
|
||||
String take_name(anim_stack->GetNameOnly());
|
||||
|
||||
motion->name = take_name;
|
||||
BakeTransformation(pNode, item, motion);
|
||||
|
||||
// Add to scene motion set.
|
||||
{
|
||||
SceneMotion *set = NULL;
|
||||
ListForeachPtr(SceneMotion *, s, scene->motion.motions)
|
||||
if (s->name == motion->name) {
|
||||
set = s;
|
||||
break;
|
||||
}
|
||||
|
||||
if (set == NULL) // create a new motion set
|
||||
{
|
||||
set = new SceneMotion;
|
||||
|
||||
set->name = take_name;
|
||||
scene->motion.motions.Add(set);
|
||||
}
|
||||
|
||||
SceneMotion::ItemMotion *item_motion = new SceneMotion::ItemMotion; // new item motion
|
||||
item_motion->uid = item->GetUid();
|
||||
item_motion->motion = motion;
|
||||
|
||||
set->item_motions.Add(item_motion); // add to set
|
||||
}
|
||||
|
||||
// Add to item motion list.
|
||||
{
|
||||
// item->automation_player->AddMotion(motion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool FBXImporter::ExportDeformers(FbxMesh *fbx_mesh, FbxNode *pNode, Geometry &geo, MObject *object) {
|
||||
FbxSkin *fbx_skin = ((FbxSkin *) fbx_mesh->GetDeformer(0, FbxDeformer::eSkin));
|
||||
if (!fbx_skin)
|
||||
return false;
|
||||
|
||||
// Allocate geometry skin.
|
||||
geo.skin.Allocate(geo.vtx.GetCount());
|
||||
|
||||
for (uint n = 0; n < geo.vtx.GetCount(); ++n)
|
||||
for (int j = 0; j < __PV_BONE_LIMIT__; ++j) {
|
||||
geo.skin[n].bone_index[j] = 0;
|
||||
geo.skin[n].w[j] = 0.f;
|
||||
}
|
||||
|
||||
// For each skin entry select the clusters with the largest weight.
|
||||
geo.AllocateBone(fbx_skin->GetClusterCount());
|
||||
|
||||
for (int n = 0; n < (int) geo.bone_name.GetCount(); ++n) {
|
||||
FbxCluster *cluster = fbx_skin->GetCluster(n);
|
||||
if (FbxNode *bone = cluster->GetLink())
|
||||
geo.bone_name[n] = bone->GetName();
|
||||
|
||||
// Import bind pose.
|
||||
FbxAMatrix cluster_matrix, bind_matrix;
|
||||
cluster->GetTransformMatrix(cluster_matrix);
|
||||
cluster->GetTransformLinkMatrix(bind_matrix);
|
||||
|
||||
geo.bone_bind_matrix[n] = FBXMatrixToMatrix4(
|
||||
(ConvertGlobalMatrix(cluster_matrix).Inverse() * ConvertGlobalMatrix(bind_matrix)).Inverse());
|
||||
|
||||
// Import weights.
|
||||
int *fbx_index = cluster->GetControlPointIndices();
|
||||
double *fbx_weight = cluster->GetControlPointWeights();
|
||||
|
||||
for (int i = 0; i < cluster->GetControlPointIndicesCount(); ++i) {
|
||||
GeometrySkin *skin = &geo.skin[fbx_index[i]];
|
||||
|
||||
// Perform insertion.
|
||||
for (int c = 0; c < __PV_BONE_LIMIT__; ++c)
|
||||
if (fbx_weight[i] > skin->w[c]) {
|
||||
// Shift the lower influences out.
|
||||
for (int j = __PV_BONE_LIMIT__ - 1; j > c; --j) {
|
||||
skin->w[j] = skin->w[j - 1];
|
||||
skin->bone_index[j] = skin->bone_index[j - 1];
|
||||
}
|
||||
|
||||
// Insert new influence.
|
||||
skin->w[c] = (float) fbx_weight[i];
|
||||
skin->bone_index[c] = (ushort) n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize weights.
|
||||
for (uint n = 0; n < geo.vtx.GetCount(); ++n) {
|
||||
GeometrySkin *skin = &geo.skin[n];
|
||||
|
||||
float w_sum = 0;
|
||||
for (int c = 0; c < __PV_BONE_LIMIT__; ++c)
|
||||
w_sum += skin->w[c];
|
||||
if (w_sum > 0)
|
||||
for (int c = 0; c < __PV_BONE_LIMIT__; ++c)
|
||||
skin->w[c] /= w_sum;
|
||||
}
|
||||
|
||||
// Set geometry and bind bones.
|
||||
object->geometry = geo.name;
|
||||
if (object->AllocateSkin(geo.GetBoneCount()))
|
||||
for (uint n = 0; n < geo.GetBoneCount(); ++n)
|
||||
if (MItem *item = ExportNode(fbx_skin->GetCluster(n)->GetLink()))
|
||||
object->BindBone(n, item->GetBaseItem());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
String FBXImporter::ExportFileTexture(FbxFileTexture *fbx_texture) {
|
||||
if (!fbx_texture)
|
||||
return NULL;
|
||||
|
||||
// Try to locate texture.
|
||||
String in_path;
|
||||
|
||||
forever {
|
||||
in_path = fbx_texture->GetFileName();
|
||||
if (Platform::Get().io->Exists(in_path))
|
||||
break;
|
||||
|
||||
in_path.FileCutPath();
|
||||
if (Platform::Get().io->Exists(in_path))
|
||||
break;
|
||||
|
||||
in_path = input_path + "/" + in_path;
|
||||
if (Platform::Get().io->Exists(in_path))
|
||||
break;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Import texture.
|
||||
String out_path;
|
||||
if (GetOutputPath(out_path, config->base_path, in_path.GetFileName(), "texture", in_path.GetFileExtension(),
|
||||
config->exists_policy_texture)) {
|
||||
Platform::Get().io->FileCopy(in_path, out_path);
|
||||
out_path = Platform::Get().io->StripRootPath(out_path);
|
||||
}
|
||||
return out_path;
|
||||
}
|
||||
|
||||
String FBXImporter::ExportLayeredTexture(FbxLayeredTexture *object) {
|
||||
String out_path;
|
||||
|
||||
for (int n = 0; n < object->GetSrcObjectCount<FbxTexture>(); ++n) {
|
||||
if (FbxFileTexture *t = object->GetSrcObject<FbxFileTexture>(n))
|
||||
out_path = ExportFileTexture(t);
|
||||
// if (FbxLayeredTexture *t = object->GetSrcObject(FBX_TYPE(FbxLayeredTexture), n))
|
||||
// texture = ExportLayeredTexture(t);
|
||||
|
||||
if (!out_path.IsEmpty())
|
||||
break;
|
||||
}
|
||||
return out_path;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
String FBXImporter::SaveMaterial(const Material &material, const char *name) {
|
||||
String out_path;
|
||||
if (GetOutputPath(out_path, config->base_path, name, "material", "nmm", config->exists_policy_material))
|
||||
NML::SaveToFile(material, out_path);
|
||||
|
||||
return Platform::Get().io->StripRootPath(out_path);
|
||||
}
|
||||
|
||||
String FBXImporter::ExportMaterial(FbxSurfaceMaterial *fbx_material, FbxMesh *fbx_mesh, bool use_skin) {
|
||||
static const char *texture_type_to_export[] =
|
||||
{
|
||||
FbxSurfaceMaterial::sDiffuse,
|
||||
FbxSurfaceMaterial::sEmissive,
|
||||
FbxSurfaceMaterial::sAmbient,
|
||||
FbxSurfaceMaterial::sSpecular,
|
||||
FbxSurfaceMaterial::sNormalMap,
|
||||
FbxSurfaceMaterial::sShininess,
|
||||
FbxSurfaceMaterial::sBump,
|
||||
FbxSurfaceMaterial::sTransparentColor,
|
||||
FbxSurfaceMaterial::sReflection,
|
||||
0
|
||||
};
|
||||
|
||||
static MaterialChannel export_texture_to_channel[] =
|
||||
{
|
||||
Channel_Diffuse,
|
||||
Channel_SelfIllum,
|
||||
Channel_Light,
|
||||
Channel_Specular,
|
||||
Channel_Normal,
|
||||
Channel_Glossiness,
|
||||
Channel_Normal,
|
||||
Channel_Opacity,
|
||||
Channel_Reflection
|
||||
};
|
||||
|
||||
if (!fbx_material)
|
||||
return NULL;
|
||||
|
||||
Material material;
|
||||
material.renderword |= Material::Render_Smooth;
|
||||
if (use_skin)
|
||||
material.renderword |= Material::Render_Skinned;
|
||||
|
||||
// Phong.
|
||||
if (fbx_material->GetClassId().Is(FbxSurfacePhong::ClassId)) {
|
||||
FbxSurfacePhong *fbx_phong = (FbxSurfacePhong *) fbx_material;
|
||||
material.specular.Set(float(fbx_phong->Specular.Get()[0] * fbx_phong->SpecularFactor.Get()),
|
||||
float(fbx_phong->Specular.Get()[1] * fbx_phong->SpecularFactor.Get()),
|
||||
float(fbx_phong->Specular.Get()[2] * fbx_phong->SpecularFactor.Get()));
|
||||
material.glossiness = Types::Clamp((float) fbx_phong->Shininess.Get() / 64.f, 0.01f, 0.5f);
|
||||
// Completely random conversion factor.
|
||||
}
|
||||
|
||||
// Lambert.
|
||||
if (fbx_material->GetClassId().Is(FbxSurfacePhong::ClassId) || fbx_material->GetClassId().Is(
|
||||
FbxSurfaceLambert::ClassId)) {
|
||||
FbxSurfaceLambert *fbx_lambert = (FbxSurfaceLambert *) fbx_material;
|
||||
material.ambient.Set(float(fbx_lambert->Ambient.Get()[0] * fbx_lambert->AmbientFactor.Get()),
|
||||
float(fbx_lambert->Ambient.Get()[1] * fbx_lambert->AmbientFactor.Get()),
|
||||
float(fbx_lambert->Ambient.Get()[2] * fbx_lambert->AmbientFactor.Get()));
|
||||
material.diffuse.Set(float(fbx_lambert->Diffuse.Get()[0] * fbx_lambert->DiffuseFactor.Get()),
|
||||
float(fbx_lambert->Diffuse.Get()[1] * fbx_lambert->DiffuseFactor.Get()),
|
||||
float(fbx_lambert->Diffuse.Get()[2] * fbx_lambert->DiffuseFactor.Get()));
|
||||
material.self.Set(float(fbx_lambert->Emissive.Get()[0] * fbx_lambert->EmissiveFactor.Get()),
|
||||
float(fbx_lambert->Emissive.Get()[1] * fbx_lambert->EmissiveFactor.Get()),
|
||||
float(fbx_lambert->Emissive.Get()[2] * fbx_lambert->EmissiveFactor.Get()));
|
||||
// material.opacity = 1.f - fbx_lambert->GetTransparencyFactor().Get(); // Broken exporters make the importer appear broken.
|
||||
}
|
||||
|
||||
// Export material textures.
|
||||
for (int t = 0; texture_type_to_export[t]; ++t) {
|
||||
// Export texture from FBX.
|
||||
FbxProperty fbx_texture_prop = fbx_material->FindProperty(texture_type_to_export[t]);
|
||||
|
||||
FbxTexture *fbx_texture = fbx_texture_prop.GetSrcObject<FbxTexture>(0);
|
||||
if (!fbx_texture)
|
||||
continue;
|
||||
|
||||
String texture;
|
||||
if (FbxFileTexture *t = fbx_texture_prop.GetSrcObject<FbxFileTexture>(0))
|
||||
texture = ExportFileTexture(t);
|
||||
if (FbxLayeredTexture *t = fbx_texture_prop.GetSrcObject<FbxLayeredTexture>(0))
|
||||
texture = ExportLayeredTexture(t);
|
||||
|
||||
// Identify UV channel.
|
||||
int uv_index = -1, uv_count = 0;
|
||||
for (int l = 0; l < fbx_mesh->GetLayerCount(); ++l) {
|
||||
FbxLayer *fbx_layer = fbx_mesh->GetLayer(l);
|
||||
|
||||
for (int n = 0; n < fbx_layer->GetUVSetCount(); ++n) {
|
||||
FbxArray<FbxLayerElement::EType> uv_types = fbx_layer->GetUVSetChannels();
|
||||
for (int t = 0; t < uv_types.GetCount(); ++t)
|
||||
if (fbx_texture->UVSet.Get() == fbx_layer->GetUVs(uv_types[t])->GetName()) {
|
||||
uv_index = uv_count;
|
||||
goto done_uv;
|
||||
}
|
||||
|
||||
++uv_count;
|
||||
if (uv_count == __UV_PER_GEOMETRY__)
|
||||
goto done_uv;
|
||||
}
|
||||
}
|
||||
|
||||
done_uv:;
|
||||
|
||||
// Create stage.
|
||||
if (Material::TextureStage *stage = material.NewStage(export_texture_to_channel[t], texture, Material::UV_UV,
|
||||
(uchar) (uv_index == -1 ? 0 : uv_index))) {
|
||||
// Normal map defaults to tangent.
|
||||
if (stage->channel == Channel_Normal)
|
||||
material.renderword |= Material::Render_NormalTangent;
|
||||
}
|
||||
}
|
||||
return SaveMaterial(material, fbx_material->GetName());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
String FBXImporter::ExportGeometry(FbxMesh *fbx_mesh, FbxNode *pNode, MObject *object) {
|
||||
// Build local transformation.
|
||||
FbxAMatrix mesh_matrix, mesh_rmatrix;
|
||||
|
||||
if (pNode) {
|
||||
mesh_matrix.SetTRS(pNode->GetGeometricTranslation(FbxNode::eSourcePivot),
|
||||
pNode->GetGeometricRotation(FbxNode::eSourcePivot),
|
||||
pNode->GetGeometricScaling(FbxNode::eSourcePivot));
|
||||
mesh_rmatrix.SetR(pNode->GetGeometricRotation(FbxNode::eSourcePivot));
|
||||
|
||||
FbxAMatrix export_global_mtx;
|
||||
export_global_mtx.SetS(FbxVector4(-1, 1, 1));
|
||||
|
||||
mesh_matrix = export_global_mtx * mesh_matrix;
|
||||
mesh_rmatrix = export_global_mtx * mesh_rmatrix;
|
||||
}
|
||||
|
||||
// Export.
|
||||
Geometry geo;
|
||||
geo.name = pNode->GetName();
|
||||
|
||||
// Transfer topology.
|
||||
geo.AllocateVertex(fbx_mesh->GetControlPointsCount());
|
||||
for (uint n = 0; n < geo.vtx.GetCount(); ++n) {
|
||||
FbxVector4 v = mesh_matrix.MultT(fbx_mesh->GetControlPoints()[n]);
|
||||
geo.vtx[n].Set((float) v[0], (float) v[1], (float) v[2]);
|
||||
}
|
||||
|
||||
geo.AllocatePolygon(fbx_mesh->GetPolygonCount());
|
||||
for (uint n = 0; n < geo.pol.GetCount(); ++n) {
|
||||
geo.pol[n].vtx_count = (ushort) fbx_mesh->GetPolygonSize(n);
|
||||
geo.pol[n].material = 0;
|
||||
}
|
||||
|
||||
Array<uint> pol_index;
|
||||
geo.ComputePolygonIndex(pol_index);
|
||||
geo.AllocatePolygonBinding();
|
||||
|
||||
#define __PolIndex (pol_index[p] + v)
|
||||
#define __PolRemapIndex (pol_index[p] + (geo.pol[p].vtx_count - 1 - v))
|
||||
// #define __PolRemapIndex (geometry->pol_index[p] + v)
|
||||
|
||||
for (uint p = 0; p < geo.pol.GetCount(); ++p)
|
||||
for (int v = 0; v < geo.pol[p].vtx_count; ++v)
|
||||
geo.pol[p].binding[v] = fbx_mesh->GetPolygonVertices()[__PolRemapIndex];
|
||||
|
||||
// Export materials.
|
||||
FbxLayer *fbx_layer = fbx_mesh->GetLayer(0);
|
||||
|
||||
// Normal.
|
||||
if (const FbxLayerElementNormal *normal_layer = fbx_layer->GetNormals())
|
||||
if (geo.vtx_normal.Allocate(geo.binding.GetCount()))
|
||||
for (uint p = 0; p < geo.pol.GetCount(); ++p)
|
||||
for (int v = 0; v < geo.pol[p].vtx_count; ++v) {
|
||||
FbxVector4 N;
|
||||
fbx_mesh->GetPolygonVertexNormal(p, v, N);
|
||||
N = mesh_rmatrix.MultT(N);
|
||||
geo.vtx_normal[__PolRemapIndex].Set((float) N[0], (float) N[1], (float) N[2]);
|
||||
}
|
||||
|
||||
// Tangent and binormal.
|
||||
const FbxLayerElementTangent *tangent_layer = fbx_layer->GetTangents();
|
||||
const FbxLayerElementBinormal *binormal_layer = fbx_layer->GetBinormals();
|
||||
|
||||
if (tangent_layer && binormal_layer) {
|
||||
if ((tangent_layer->GetMappingMode() == FbxLayerElement::eByPolygonVertex) && (
|
||||
binormal_layer->GetMappingMode() == FbxLayerElement::eByPolygonVertex)) {
|
||||
if (geo.vtx_tangent.Allocate(geo.binding.GetCount()))
|
||||
for (uint p = 0; p < geo.pol.GetCount(); ++p)
|
||||
for (int v = 0; v < geo.pol[p].vtx_count; ++v) {
|
||||
FbxVector4 T = tangent_layer->GetReferenceMode() == FbxLayerElement::eIndexToDirect
|
||||
? tangent_layer->GetDirectArray()[tangent_layer->GetIndexArray()[
|
||||
__PolRemapIndex]]
|
||||
: tangent_layer->GetDirectArray()[__PolRemapIndex];
|
||||
T = mesh_rmatrix.MultT(T);
|
||||
geo.vtx_tangent[__PolIndex].T.Set((float) T[0], (float) -T[1], (float) T[2]);
|
||||
// This is UV dependent and textures are reversed on V from the FBX convention.
|
||||
|
||||
FbxVector4 B = binormal_layer->GetReferenceMode() == FbxLayerElement::eIndexToDirect
|
||||
? binormal_layer->GetDirectArray()[binormal_layer->GetIndexArray()[
|
||||
__PolRemapIndex]]
|
||||
: binormal_layer->GetDirectArray()[__PolRemapIndex];
|
||||
B = mesh_rmatrix.MultT(T);
|
||||
geo.vtx_tangent[__PolIndex].B.Set((float) B[0], (float) -B[1], (float) B[2]);
|
||||
// This is UV dependent and textures are reversed on V from the FBX convention.
|
||||
}
|
||||
} else
|
||||
__LOG_W__ << "Unsupported tangent layer mapping mode (" << tangent_layer->GetMappingMode() << ").\n";
|
||||
}
|
||||
|
||||
// Vertex color.
|
||||
if (const FbxLayerElementVertexColor *color_layer = fbx_layer->GetVertexColors()) {
|
||||
if (geo.rgb.Allocate(geo.binding.GetCount()))
|
||||
switch (color_layer->GetMappingMode()) {
|
||||
case FbxLayerElement::eByControlPoint:
|
||||
for (uint p = 0; p < geo.pol.GetCount(); ++p)
|
||||
for (int v = 0; v < geo.pol[p].vtx_count; ++v) {
|
||||
uint v_idx = geo.pol[p].binding[v];
|
||||
const FbxColor &cl = color_layer->GetReferenceMode() == FbxLayerElement::eIndexToDirect
|
||||
? color_layer->GetDirectArray()[color_layer->GetIndexArray()[
|
||||
v_idx]]
|
||||
: color_layer->GetDirectArray()[v_idx];
|
||||
geo.rgb[__PolIndex].Set((float) cl.mRed, (float) cl.mGreen, (float) cl.mBlue);
|
||||
}
|
||||
break;
|
||||
|
||||
case FbxLayerElement::eByPolygonVertex:
|
||||
for (uint p = 0; p < geo.pol.GetCount(); ++p)
|
||||
for (int v = 0; v < geo.pol[p].vtx_count; ++v) {
|
||||
const FbxColor &cl = color_layer->GetReferenceMode() == FbxLayerElement::eIndexToDirect
|
||||
? color_layer->GetDirectArray()[color_layer->GetIndexArray()[
|
||||
__PolRemapIndex]]
|
||||
: color_layer->GetDirectArray()[__PolRemapIndex];
|
||||
geo.rgb[__PolIndex].Set((float) cl.mRed, (float) cl.mGreen, (float) cl.mBlue);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
__LOG_W__ << "Unsupported vertex color layer mapping mode (" << color_layer->GetMappingMode() <<
|
||||
").\n";
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate vertex color set.\n";
|
||||
}
|
||||
|
||||
// UV Channel (searched for on all available layers).
|
||||
uint uv_count = 0;
|
||||
for (int l = 0; l < fbx_mesh->GetLayerCount(); ++l) {
|
||||
FbxLayer *fbx_layer = fbx_mesh->GetLayer(l);
|
||||
|
||||
for (int n = 0; n < fbx_layer->GetUVSetCount(); ++n) {
|
||||
const FbxLayerElementUV *uv_layer = fbx_layer->GetUVSets()[n];
|
||||
|
||||
if (geo.uv[uv_count].Allocate(geo.binding.GetCount()))
|
||||
switch (uv_layer->GetMappingMode()) {
|
||||
case FbxLayerElement::eByControlPoint:
|
||||
for (uint p = 0; p < geo.pol.GetCount(); ++p)
|
||||
for (int v = 0; v < geo.pol[p].vtx_count; ++v) {
|
||||
uint v_idx = geo.pol[p].binding[v];
|
||||
const FbxVector2 &UV = uv_layer->GetReferenceMode() == FbxLayerElement::eIndexToDirect
|
||||
? uv_layer->GetDirectArray()[uv_layer->GetIndexArray()[
|
||||
v_idx]]
|
||||
: uv_layer->GetDirectArray()[v_idx];
|
||||
geo.uv[uv_count][__PolIndex].Set((float) UV[0], 1.f - (float) UV[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case FbxLayerElement::eByPolygonVertex:
|
||||
for (uint p = 0; p < geo.pol.GetCount(); ++p)
|
||||
for (int v = 0; v < geo.pol[p].vtx_count; ++v) {
|
||||
const FbxVector2 &UV = uv_layer->GetReferenceMode() == FbxLayerElement::eIndexToDirect
|
||||
? uv_layer->GetDirectArray()[uv_layer->GetIndexArray()[
|
||||
__PolRemapIndex]]
|
||||
: uv_layer->GetDirectArray()[__PolRemapIndex];
|
||||
geo.uv[uv_count][__PolIndex].Set((float) UV[0], 1.f - (float) UV[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
__LOG_W__ << "Unsupported UV layer mapping mode (" << uv_layer->GetMappingMode() << ").\n";
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate UV set.\n";
|
||||
|
||||
if (++uv_count == __UV_PER_GEOMETRY__) {
|
||||
__LOG_W__ << "UV map limit per geometry exceeded (" << __UV_PER_GEOMETRY__ <<
|
||||
"), increase nUVMapLimit.\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (uv_count == __UV_PER_GEOMETRY__)
|
||||
break;
|
||||
}
|
||||
|
||||
// Export deformers.
|
||||
bool use_skin = ExportDeformers(fbx_mesh, pNode, geo, object);
|
||||
|
||||
// Materials.
|
||||
int material_count = fbx_mesh->GetNode()->GetMaterialCount();
|
||||
|
||||
if (material_count > 0) {
|
||||
geo.material_table.Allocate(material_count);
|
||||
for (int n = 0; n < material_count; ++n)
|
||||
geo.material_table[n].name = ExportMaterial((FbxSurfaceMaterial *) fbx_mesh->GetNode()->GetMaterial(n),
|
||||
fbx_mesh, use_skin);
|
||||
} else {
|
||||
Material material;
|
||||
if (use_skin)
|
||||
material.renderword |= Material::Render_Skinned;
|
||||
|
||||
geo.material_table.Allocate(1);
|
||||
geo.material_table[0].name = SaveMaterial(material, geo.name);
|
||||
}
|
||||
|
||||
// Export the material mapping to polygon.
|
||||
const FbxLayerElementMaterial *material_layer = fbx_layer->GetMaterials();
|
||||
|
||||
if (material_layer)
|
||||
switch (material_layer->GetMappingMode()) {
|
||||
case FbxLayerElement::eByPolygon: {
|
||||
// Map polygon to material.
|
||||
if (material_layer->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
|
||||
for (uint n = 0; n < geo.pol.GetCount(); ++n) {
|
||||
int idx = material_layer->GetIndexArray().GetAt(n);
|
||||
geo.pol[n].material = (ushort) idx;
|
||||
if (geo.pol[n].material >= geo.material_table.GetCount()) {
|
||||
__LOG_E__ << "Invalid material index (" << idx << ") for polygon " << n <<
|
||||
" (FBX powered).\n";
|
||||
geo.pol[n].material = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
for (uint n = 0; n < geo.pol.GetCount(); ++n)
|
||||
geo.pol[n].material = (ushort) n;
|
||||
}
|
||||
break;
|
||||
|
||||
case FbxLayerElement::eAllSame: {
|
||||
if (material_layer->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
|
||||
for (uint n = 0; n < geo.pol.GetCount(); ++n) {
|
||||
int idx = material_layer->GetIndexArray().GetAt(0);
|
||||
geo.pol[n].material = (ushort) idx;
|
||||
if (geo.pol[n].material >= geo.material_table.GetCount()) {
|
||||
__LOG_E__ << "Invalid material index (" << idx << ") for polygon " << n <<
|
||||
" (FBX powered).\n";
|
||||
geo.pol[n].material = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
for (uint n = 0; n < geo.pol.GetCount(); ++n)
|
||||
geo.pol[n].material = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
__LOG_W__ << "Unsupported material mapping mode (" << material_layer->GetMappingMode() << ").\n";
|
||||
break;
|
||||
}
|
||||
|
||||
// Output to path.
|
||||
String out_path;
|
||||
if (GetOutputPath(out_path, config->base_path, geo.name, "geometry", "nmg", config->exists_policy_geometry)) {
|
||||
geo.name = out_path;
|
||||
NML::SaveToFile(geo, geo.name);
|
||||
geo.name = Platform::Get().io->StripRootPath(geo.name);
|
||||
}
|
||||
|
||||
object->geometry = geo.name;
|
||||
return geo.name;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MObject *FBXImporter::ExportObject(FbxNodeAttribute *pAttr, FbxNode *pNode) {
|
||||
FbxMesh *fbx_mesh = (FbxMesh *) pAttr;
|
||||
MObject *object = new MObject;
|
||||
object->name = pNode->GetNameOnly();
|
||||
scene->AddItem(object, true);
|
||||
ExportGeometry(fbx_mesh, pNode, object);
|
||||
return object;
|
||||
}
|
||||
|
||||
MItem *FBXImporter::ExportCamera(FbxNodeAttribute *pAttr, FbxNode *pNode) {
|
||||
FbxCamera *fbx_camera = (FbxCamera *) pAttr;
|
||||
MCamera *camera = new MCamera;
|
||||
camera->name = pNode->GetNameOnly();
|
||||
scene->AddItem(camera, true);
|
||||
|
||||
if (fbx_camera->GetNearPlane() != 10)
|
||||
camera->SetNearClippingPlane((float) fbx_camera->GetNearPlane());
|
||||
if (fbx_camera->GetFarPlane() != 4000)
|
||||
camera->SetFarClippingPlane((float) fbx_camera->GetFarPlane());
|
||||
|
||||
camera->aspect_ratio = (float) fbx_camera->GetPixelRatio();
|
||||
camera->SetFov(Units::DegreeToRadian((float) fbx_camera->FieldOfView.Get()));
|
||||
camera->is_orthographic = asbool(fbx_camera->ProjectionType.Get() == FbxCamera::eOrthogonal);
|
||||
|
||||
return camera;
|
||||
}
|
||||
|
||||
MItem *FBXImporter::ExportLight(FbxNodeAttribute *pAttr, FbxNode *pNode) {
|
||||
FbxLight *fbx_light = (FbxLight *) pAttr;
|
||||
MLight *light = new MLight;
|
||||
light->name = pNode->GetNameOnly();
|
||||
scene->AddItem(light, true);
|
||||
|
||||
switch (fbx_light->LightType.Get()) {
|
||||
case FbxLight::ePoint: light->model = MLight::Model_Point;
|
||||
break;
|
||||
case FbxLight::eDirectional: light->model = MLight::Model_Linear;
|
||||
break;
|
||||
case FbxLight::eSpot: light->model = MLight::Model_Spot;
|
||||
break;
|
||||
}
|
||||
|
||||
light->diffuse_color.Set((float) fbx_light->Color.Get()[0], (float) fbx_light->Color.Get()[1],
|
||||
(float) fbx_light->Color.Get()[2]);
|
||||
light->diffuse_intensity = (float) fbx_light->Intensity.Get() / 100.f;
|
||||
light->specular_color = light->diffuse_color;
|
||||
|
||||
if (fbx_light->EnableFarAttenuation.Get()) {
|
||||
light->range = (float) fbx_light->FarAttenuationEnd.Get();
|
||||
light->volume_range = light->range + Units::Mtr(0.5f);
|
||||
}
|
||||
|
||||
if (fbx_light->CastShadows.Get())
|
||||
light->shadow = Light::Shadow_Map;
|
||||
light->shadow_color.Set((float) fbx_light->ShadowColor.Get()[0], (float) fbx_light->ShadowColor.Get()[1],
|
||||
(float) fbx_light->ShadowColor.Get()[2]);
|
||||
return light;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool FBXImporter::GetNodeItem(FbxNode *pNode, MItem **item) {
|
||||
ListForeachPtr(ExportedNode *, exported_node, node_list)
|
||||
if (exported_node->node == pNode) {
|
||||
if (item)
|
||||
*item = exported_node->item;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
MItem *FBXImporter::ExportNode(FbxNode *pNode) {
|
||||
if (config->event_handler)
|
||||
config->event_handler->LoadProgress(String::Format("Importing node '%s'...", pNode->GetName()),
|
||||
(float) current_node_index / fbx_scene->GetNodeCount());
|
||||
current_node_index++;
|
||||
|
||||
MItem *item = NULL;
|
||||
if (GetNodeItem(pNode, &item))
|
||||
return item;
|
||||
|
||||
// Export this node.
|
||||
if (pNode != fbx_scene->GetRootNode()) {
|
||||
if (pNode->GetNodeAttribute()) {
|
||||
FbxNodeAttribute::EType type = pNode->GetNodeAttribute()->GetAttributeType();
|
||||
|
||||
switch (type) {
|
||||
default:
|
||||
case FbxNodeAttribute::eUnknown:
|
||||
case FbxNodeAttribute::eNull:
|
||||
case FbxNodeAttribute::eMarker:
|
||||
case FbxNodeAttribute::eNurbs:
|
||||
case FbxNodeAttribute::ePatch:
|
||||
case FbxNodeAttribute::eCameraStereo:
|
||||
case FbxNodeAttribute::eCameraSwitcher:
|
||||
case FbxNodeAttribute::eOpticalReference:
|
||||
case FbxNodeAttribute::eOpticalMarker:
|
||||
case FbxNodeAttribute::eNurbsCurve:
|
||||
case FbxNodeAttribute::eTrimNurbsSurface:
|
||||
case FbxNodeAttribute::eBoundary:
|
||||
case FbxNodeAttribute::eNurbsSurface:
|
||||
case FbxNodeAttribute::eShape:
|
||||
case FbxNodeAttribute::eLODGroup:
|
||||
case FbxNodeAttribute::eSubDiv:
|
||||
case FbxNodeAttribute::eSkeleton:
|
||||
if (MObject *o = new MObject) {
|
||||
o->name = pNode->GetNameOnly();
|
||||
scene->AddItem(o, true);
|
||||
item = o;
|
||||
}
|
||||
break;
|
||||
|
||||
case FbxNodeAttribute::eMesh:
|
||||
item = ExportObject(pNode->GetNodeAttribute(), pNode);
|
||||
break;
|
||||
case FbxNodeAttribute::eCamera:
|
||||
item = ExportCamera(pNode->GetNodeAttribute(), pNode);
|
||||
break;
|
||||
case FbxNodeAttribute::eLight:
|
||||
item = ExportLight(pNode->GetNodeAttribute(), pNode);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
MObject *o = new MObject;
|
||||
o->name = pNode->GetNameOnly();
|
||||
scene->AddItem(o, true);
|
||||
item = o;
|
||||
}
|
||||
}
|
||||
|
||||
// Register node.
|
||||
node_list.Add(new ExportedNode(pNode, item));
|
||||
|
||||
if (item) {
|
||||
FbxAMatrix m;
|
||||
if (pNode->GetParent())
|
||||
m = ConvertGlobalMatrix(fbx_scene->GetEvaluator()->GetNodeGlobalTransform(pNode->GetParent())).Inverse() *
|
||||
ConvertGlobalMatrix(fbx_scene->GetEvaluator()->GetNodeGlobalTransform(pNode));
|
||||
else m = ConvertGlobalMatrix(fbx_scene->GetEvaluator()->GetNodeGlobalTransform(pNode));
|
||||
|
||||
item->GetBaseItem()->SetMatrix(FBXMatrixToMatrix4(m));
|
||||
ExportMotions(pNode, item);
|
||||
}
|
||||
|
||||
// Export children.
|
||||
for (int i = 0; i < pNode->GetChildCount(); i++) {
|
||||
MItem *child = ExportNode(pNode->GetChild(i));
|
||||
if (child && item)
|
||||
child->GetBaseItem()->SetParent(item->GetBaseItem());
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool FBXImporter::TestImport(const char *uri) {
|
||||
String ext = String::FileGetExtension(uri).Lower();
|
||||
return asbool((ext == "dae") || (ext == "fbx") || (ext == "3ds"));
|
||||
}
|
||||
|
||||
bool FBXImporter::ImportScene(Scene *_scene, const char *_input, const Config &_config, Group **) {
|
||||
if (!sdk_manager)
|
||||
__ERR__(__LOG_E__ << "Importer not initialized.\n", false)
|
||||
if (_input == NULL)
|
||||
__ERR__(__LOG_E__ << "No input file specified.\n", false)
|
||||
if (_scene == NULL)
|
||||
__ERR__(__LOG_E__ << "No scene to load into.\n", false)
|
||||
|
||||
// Load native FBX.
|
||||
scene = _scene;
|
||||
config = &_config;
|
||||
if ((fbx_scene = LoadNativeScene(_input)) == NULL)
|
||||
return false;
|
||||
|
||||
if (config->event_handler)
|
||||
config->event_handler->OpenLoad();
|
||||
|
||||
// Drop lists.
|
||||
geometry_list.Clear();
|
||||
|
||||
// Perform conversion.
|
||||
current_node_index = 0;
|
||||
ExportNode(fbx_scene->GetRootNode());
|
||||
|
||||
// Convert globals.
|
||||
FbxGlobalLightSettings &gsettings = fbx_scene->GlobalLightSettings();
|
||||
|
||||
scene->ambient_color.Set((float) gsettings.GetAmbientColor().mRed, (float) gsettings.GetAmbientColor().mGreen,
|
||||
(float) gsettings.GetAmbientColor().mBlue);
|
||||
scene->ambient_intensity = 1.f;
|
||||
|
||||
scene->fog_color.Set((float) gsettings.GetFogColor().mRed, (float) gsettings.GetFogColor().mGreen,
|
||||
(float) gsettings.GetFogColor().mBlue);
|
||||
if (gsettings.GetFogEnable()) {
|
||||
scene->fog_near = (float) gsettings.GetFogStart();
|
||||
scene->fog_far = (float) gsettings.GetFogEnd();
|
||||
}
|
||||
|
||||
// Save.
|
||||
if (!config->base_path.IsEmpty()) {
|
||||
scene->name = String::Format("%s/%s.nms", config->base_path.toUtf8(),
|
||||
String(_input).CutFilePath().CutFileExtension().toUtf8());
|
||||
NML::SaveToFile(*scene, scene->name);
|
||||
scene->name = Platform::Get().io->StripRootPath(scene->name);
|
||||
}
|
||||
|
||||
fbx_scene->Destroy();
|
||||
ListDeleteAllPtr(ExportedNode *, node_list)
|
||||
|
||||
if (config->event_handler)
|
||||
config->event_handler->EndLoad();
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
FBXImporter::FBXImporter() {
|
||||
sdk_manager = FbxManager::Create();
|
||||
fbx_scene = NULL;
|
||||
}
|
||||
|
||||
FBXImporter::~FBXImporter() {
|
||||
if (sdk_manager)
|
||||
sdk_manager->Destroy();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
683
include/modules/import_obj/import_obj.cpp
Normal file
683
include/modules/import_obj/import_obj.cpp
Normal file
@ -0,0 +1,683 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "import_obj/import_obj.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "core/graphic_resource_factory.h"
|
||||
#include "core/geometry.h"
|
||||
#include "metafile/nml_object.h"
|
||||
#include "ascii/parser.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "platform.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::AsciiParser;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct ObjPoly
|
||||
{
|
||||
List <int> vtx, uv, nrm;
|
||||
uint mat;
|
||||
|
||||
ObjPoly() : mat(0) {}
|
||||
};
|
||||
struct ObjGroup
|
||||
{
|
||||
String name;
|
||||
List <ObjPoly *> pol_list;
|
||||
|
||||
void Free()
|
||||
{ ListDeleteAllPtr(ObjPoly *, pol_list) }
|
||||
~ObjGroup()
|
||||
{ Free(); }
|
||||
};
|
||||
struct ObjMtl
|
||||
{
|
||||
String name;
|
||||
String path;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void ExportMaterialStage(NML::Tag *mtag, const String &texture, const char *channel, int index)
|
||||
{
|
||||
if (texture.IsEmpty())
|
||||
return;
|
||||
|
||||
if (NML::Tag *ttag = mtag->AddChild("TextureStage"))
|
||||
{
|
||||
ttag->AddChild("Active");
|
||||
ttag->AddChild("Texture", texture);
|
||||
ttag->AddChild("Channel", channel);
|
||||
ttag->AddChild("Index", index);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool OBJImporter::LoadMaterialLibrary(List <ObjMtl *> &mtl_list, const char *uri)
|
||||
{
|
||||
Array <char> obj;
|
||||
if (!Platform::Get().io->FileLoad(uri, obj))
|
||||
__ERR__(__LOG_E__ << "OBJ material library file '" << uri << "' not found.\n", false)
|
||||
|
||||
// Now parse.
|
||||
const char *pobj = &obj[0], *eobj = pobj + obj.GetSize();
|
||||
|
||||
ObjMtl *current_mtl = NULL;
|
||||
String map_Ka, map_Kd, map_Ks, map_Ke;
|
||||
|
||||
forever
|
||||
{
|
||||
String word(pobj, SkipEntry(pobj, eobj));
|
||||
|
||||
// Export material to file.
|
||||
if ((word == "newmtl") || (pobj >= eobj))
|
||||
if (current_mtl)
|
||||
{
|
||||
current_mtl->path = String::Format("%s/%s.nmm", config->base_path.c_str(), current_mtl->name.c_str());
|
||||
|
||||
// Only export material if it does not exist.
|
||||
if (!Platform::Get().io->Exists(current_mtl->path))
|
||||
{
|
||||
String name = Platform::Get().io->StripRootPath(current_mtl->path);
|
||||
|
||||
NML::File file;
|
||||
if (NML::Tag *mtag = file.AddRoot("Material"))
|
||||
{
|
||||
mtag->AddChild("Id", name);
|
||||
|
||||
ExportMaterialStage(mtag, map_Kd, "Diffuse", 0);
|
||||
ExportMaterialStage(mtag, map_Ka, "Opacity", 1);
|
||||
ExportMaterialStage(mtag, map_Ks, "Specular", 2);
|
||||
ExportMaterialStage(mtag, map_Ke, "Emissive", 3);
|
||||
|
||||
if (NML::Tag *rtag = mtag->AddChild("RenderMask"))
|
||||
rtag->AddChild("NormalMapTangent");
|
||||
}
|
||||
|
||||
NML::Parser::Save(current_mtl->path, file);
|
||||
}
|
||||
}
|
||||
|
||||
if (pobj >= eobj)
|
||||
break;
|
||||
|
||||
// Create new material.
|
||||
if (word == "newmtl")
|
||||
{
|
||||
// Create new material.
|
||||
mtl_list.Add(current_mtl = new ObjMtl);
|
||||
|
||||
pobj = NextEntry(pobj + 1, eobj);
|
||||
const char *eon = SkipEntry(pobj, eobj);
|
||||
|
||||
current_mtl->name.Set(pobj, eon);
|
||||
pobj = NextEntry(eon, eobj, true);
|
||||
}
|
||||
else if (current_mtl)
|
||||
{
|
||||
//------------------------------------------------------------------
|
||||
#define __ReadObjMaterialMap(_map) \
|
||||
{ \
|
||||
pobj = NextEntry(pobj + 1, eobj); \
|
||||
const char *eon = RunToEOL(pobj, eobj); \
|
||||
_map.Set(pobj, eon); \
|
||||
pobj = NextEntry(eon, eobj, true); \
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
||||
if (word == "map_Ka")
|
||||
__ReadObjMaterialMap(map_Ka)
|
||||
else if (word == "map_Ks")
|
||||
__ReadObjMaterialMap(map_Ks)
|
||||
else if (word == "map_Kd")
|
||||
__ReadObjMaterialMap(map_Kd)
|
||||
else if (word == "map_Ke")
|
||||
__ReadObjMaterialMap(map_Ke)
|
||||
else
|
||||
pobj = NextEntry(RunToEOL(pobj, eobj), eobj);
|
||||
}
|
||||
else
|
||||
pobj = NextEntry(RunToEOL(pobj, eobj), eobj);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool OBJImporter::TestImport(const char *uri)
|
||||
{
|
||||
String ext = String::FileGetExtension(uri).Lower();
|
||||
return ext == "obj";
|
||||
}
|
||||
bool OBJImporter::ImportScene(Scene *scene, const char *uri, const Config &_config, Group **)
|
||||
{
|
||||
Array <char> obj;
|
||||
if (!Platform::Get().io->FileLoad(uri, obj))
|
||||
__ERR__(__LOG_E__ << "OBJ file '" << uri << "' not found.\n", false)
|
||||
|
||||
// Now parse.
|
||||
config = &_config;
|
||||
if (config->event_handler)
|
||||
config->event_handler->OpenLoad();
|
||||
|
||||
const char *pobj = &obj[0], *eobj = pobj + obj.GetSize();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
{
|
||||
bool has_uv = false, has_vnm = false;
|
||||
AutoList <Vector4 *> vtx_list, vnm_list;
|
||||
AutoList <Vector2 *> uv_list;
|
||||
|
||||
AutoList <ObjGroup *> group_list;
|
||||
AutoList <ObjMtl *> mat_list;
|
||||
|
||||
ObjGroup *current_group = new ObjGroup;
|
||||
current_group->name = "default";
|
||||
group_list.Add(current_group);
|
||||
|
||||
int current_mat = 0;
|
||||
|
||||
while (pobj < eobj)
|
||||
{
|
||||
String word(pobj, SkipEntry(pobj, eobj));
|
||||
|
||||
if (config->event_handler)
|
||||
config->event_handler->LoadProgress(String::Format("Parsing tag '%s'...", word.c_str()), (float)(pobj - &obj[0]) / obj.GetSize());
|
||||
|
||||
// Declare material library.
|
||||
if (word == "mtllib")
|
||||
{
|
||||
pobj = NextEntry(pobj + 1, eobj);
|
||||
const char *eon = RunToEOL(pobj, eobj);
|
||||
|
||||
String lib_path = String(pobj, eon);
|
||||
if (!lib_path.IsAbsolutePath())
|
||||
lib_path = String(uri).GetFilePath() + "/" + lib_path;
|
||||
|
||||
LoadMaterialLibrary(mat_list, lib_path);
|
||||
pobj = NextEntry(eon, eobj, true);
|
||||
}
|
||||
|
||||
// Use material.
|
||||
else if (word == "usemtl")
|
||||
{
|
||||
pobj = NextEntry(pobj + 1, eobj);
|
||||
const char *eon = SkipEntry(pobj, eobj);
|
||||
String name(pobj, eon);
|
||||
|
||||
// Locate in library.
|
||||
current_mat = 0;
|
||||
ListForeachPtr(ObjMtl *, mat, mat_list)
|
||||
{
|
||||
if (mat->name == name)
|
||||
break;
|
||||
current_mat++;
|
||||
}
|
||||
|
||||
pobj = NextEntry(eon, eobj, true);
|
||||
}
|
||||
|
||||
// Append vertex.
|
||||
else if (word == "v")
|
||||
{
|
||||
// Parse vertex.
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
float x = 0, y = 0, z = 0;
|
||||
|
||||
x = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
y = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
z = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
vtx_list.Add(new Vector4(x * config->scale, y * config->scale, -z * config->scale));
|
||||
}
|
||||
|
||||
// Append vertex normal.
|
||||
else if (word == "vn")
|
||||
{
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
float x = 0, y = 0, z = 0;
|
||||
|
||||
x = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
y = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
z = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
// vnm_list.Add(new nVector(-y, -z, -x));
|
||||
vnm_list.Add(new Vector4(x, y, -z));
|
||||
}
|
||||
|
||||
// Append UV.
|
||||
else if (word == "vt")
|
||||
{
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
float u = 0, v = 0;
|
||||
|
||||
u = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
v = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
uv_list.Add(new Vector2(u, 1.f - v));
|
||||
}
|
||||
|
||||
// Declare group.
|
||||
else if (word == "g")
|
||||
{
|
||||
group_list.Add(current_group = new ObjGroup);
|
||||
|
||||
// Check for named group.
|
||||
const char *eol = RunToEOL(pobj, eobj);
|
||||
pobj = NextEntry(pobj + 1, eobj);
|
||||
|
||||
if (pobj <= eol)
|
||||
{
|
||||
const char *eon = SkipEntry(pobj, eobj);
|
||||
current_group->name.Set(pobj, eon);
|
||||
pobj = NextEntry(eon, eobj, true);
|
||||
}
|
||||
else // no name
|
||||
pobj = NextEntry(eol, eobj, true);
|
||||
}
|
||||
|
||||
// Build group polygons.
|
||||
else if (word == "f")
|
||||
{
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
ObjPoly *pol = new ObjPoly;
|
||||
pol->mat = current_mat;
|
||||
|
||||
const char *eol = RunToEOL(pobj, eobj);
|
||||
while (pobj < eol)
|
||||
{
|
||||
pol->vtx.Add(String::atoi(pobj)); // Index.
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
if (pobj[0] == '/')
|
||||
{
|
||||
pobj++;
|
||||
if (pobj[0] != '/')
|
||||
{
|
||||
has_uv = true;
|
||||
pol->uv.Add(String::atoi(pobj)); // UV index.
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (pobj[0] == '/')
|
||||
{
|
||||
pobj++;
|
||||
has_vnm = true;
|
||||
pol->nrm.Add(String::atoi(pobj)); // Normal index.
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (pol->vtx.GetCount() < 3)
|
||||
delete pol;
|
||||
else
|
||||
current_group->pol_list.Add(pol);
|
||||
}
|
||||
else
|
||||
pobj = NextEntry(RunToEOL(pobj, eobj), eobj);
|
||||
}
|
||||
|
||||
obj.Free();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Get flat UV array.
|
||||
Array <Vector2> flat_uv;
|
||||
if (has_uv && flat_uv.Allocate(uv_list.GetCount()))
|
||||
{
|
||||
Vector2 *pflat_uv = flat_uv;
|
||||
ListForeachPtr(Vector2 *, uv, uv_list)
|
||||
*pflat_uv++ = *uv;
|
||||
}
|
||||
|
||||
// Get flat vertex normal array.
|
||||
Array <Vector4> flat_vnm;
|
||||
if (has_vnm && flat_vnm.Allocate(vnm_list.GetCount()))
|
||||
{
|
||||
Vector4 *pflat_vnm = flat_vnm;
|
||||
ListForeachPtr(Vector4 *, vnm, vnm_list)
|
||||
*pflat_vnm++ = *vnm;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
Array <int> vtx_map(vtx_list.GetCount()),
|
||||
mat_map(mat_list.GetCount());
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Build scene.
|
||||
int n_pg = 0;
|
||||
ListForeachPtr(ObjGroup *, group, group_list)
|
||||
{
|
||||
++n_pg;
|
||||
if (!vtx_list.GetCount() || !group->pol_list.GetCount())
|
||||
continue;
|
||||
|
||||
if (config->event_handler)
|
||||
config->event_handler->LoadProgress(String::Format("Importing group '%s'...", group->name.toUtf8()), (float)(n_pg - 1) / group_list.GetCount());
|
||||
|
||||
// Create geometry.
|
||||
Geometry *geo = new Geometry;
|
||||
|
||||
// Remap vertices.
|
||||
for (uint n = 0; n < vtx_map.GetCount(); ++n)
|
||||
vtx_map[n] = -1;
|
||||
|
||||
// Total vertex count.
|
||||
uint vtx_count = 0;
|
||||
ListForeachPtr(ObjPoly *, p, group->pol_list)
|
||||
ListForeachPtr(int, i, p->vtx)
|
||||
if (vtx_map[i - 1] == -1)
|
||||
vtx_map[i - 1] = vtx_count++;
|
||||
|
||||
// Transfer vertices.
|
||||
if (geo->vtx.Allocate(vtx_count))
|
||||
{
|
||||
for (uint i = 0; i < vtx_list.GetCount(); ++i)
|
||||
if (vtx_map[i] != -1)
|
||||
geo->vtx[vtx_map[i]] = *vtx_list[i];
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate " << geo->vtx.GetCount() << " vertices.\n";
|
||||
|
||||
// Transfer topology and attributes.
|
||||
if (geo->pol.Allocate(group->pol_list.GetCount()))
|
||||
{
|
||||
// Compute bind index count.
|
||||
uint binding_count = 0;
|
||||
ListForeachPtr(ObjPoly *, p, group->pol_list)
|
||||
binding_count += p->vtx.GetCount();
|
||||
|
||||
if (geo->binding.Allocate(binding_count))
|
||||
{
|
||||
uint *pbind = &geo->binding[0];
|
||||
|
||||
// Allocate attributes.
|
||||
Vector2 *puv = NULL;
|
||||
if (has_uv)
|
||||
{
|
||||
geo->uv[0].Allocate(binding_count);
|
||||
puv = &geo->uv[0][0];
|
||||
}
|
||||
|
||||
Vector4 *pvnm = NULL;
|
||||
if (has_vnm)
|
||||
{
|
||||
geo->vtx_normal.Allocate(binding_count);
|
||||
pvnm = &geo->vtx_normal[0];
|
||||
}
|
||||
|
||||
// Transfer data.
|
||||
uint cpol = 0;
|
||||
ListForeachPtr(ObjPoly *, p, group->pol_list)
|
||||
{
|
||||
Polygon *pol = &geo->pol[cpol++];
|
||||
|
||||
pol->vtx_count = (ushort)p->vtx.GetCount();
|
||||
pol->binding = pbind;
|
||||
pol->material = 0;
|
||||
|
||||
for (int i = p->vtx.GetCount(); i > 0; --i)
|
||||
{
|
||||
int idx = p->vtx[i - 1] - 1;
|
||||
if (idx > (int)vtx_map.GetCount())
|
||||
idx = 0;
|
||||
*pbind++ = vtx_map[idx];
|
||||
}
|
||||
|
||||
if (puv)
|
||||
for (int i = p->uv.GetCount(); i > 0; --i)
|
||||
*puv++ = flat_uv[p->uv[i - 1] - 1];
|
||||
|
||||
if (pvnm)
|
||||
for (int i = p->nrm.GetCount(); i > 0; --i)
|
||||
*pvnm++ = flat_vnm[p->nrm[i - 1] - 1];
|
||||
}
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate " << geo->binding.GetCount() << " polygon binding entries.\n";
|
||||
|
||||
// Remap and assign materials.
|
||||
for (uint i = 0; i < mat_list.GetCount(); ++i)
|
||||
mat_map[i] = -1;
|
||||
|
||||
int mat_count = 0;
|
||||
ListForeachPtr(ObjPoly *, p, group->pol_list)
|
||||
if (p->mat < mat_map.GetCount())
|
||||
if (mat_map[p->mat] == -1)
|
||||
mat_map[p->mat] = mat_count++;
|
||||
|
||||
uint cpol = 0;
|
||||
ListForeachPtr(ObjPoly *, p, group->pol_list)
|
||||
geo->pol[cpol++].material = (ushort)(p->mat < mat_map.GetCount() ? mat_map[p->mat] : 0);
|
||||
|
||||
// Load materials.
|
||||
if (mat_list.GetCount())
|
||||
{
|
||||
geo->material_table.Allocate(mat_count);
|
||||
for (uint i = 0; i < mat_list.GetCount(); ++i)
|
||||
if (mat_map[i] != -1)
|
||||
geo->material_table[mat_map[i]].name = mat_list[i]->path;
|
||||
}
|
||||
else
|
||||
geo->material_table.Allocate(1);
|
||||
|
||||
// Vertex normal.
|
||||
if (!has_vnm)
|
||||
geo->ComputeVertexNormal(true);
|
||||
|
||||
// Save geometry.
|
||||
geo->name = String::Format("%s/%s.nmg", config->base_path.c_str(), group->name.toUtf8());
|
||||
NML::SaveToFile(*geo, geo->name);
|
||||
|
||||
geo->name = Platform::Get().io->StripRootPath(geo->name);
|
||||
|
||||
// Add to scene.
|
||||
MObject *object = new MObject;
|
||||
object->name = group->name;
|
||||
scene->AddItem(object, true);
|
||||
object->geometry = geo->name;
|
||||
|
||||
// Ease up memory.
|
||||
group->Free();
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate " << geo->pol.GetCount() << " polygons.\n";
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Save scene.
|
||||
scene->name = String::Format("%s/scene.nms", config->base_path.c_str());
|
||||
NML::SaveToFile(*scene, scene->name);
|
||||
scene->name = Platform::Get().io->StripRootPath(scene->name);
|
||||
|
||||
if (config->event_handler)
|
||||
config->event_handler->EndLoad();
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Geometry *OBJImporter::ImportGeometry(const char *uri, IResourceFactoryEvent *event_handler)
|
||||
{
|
||||
if (!uri)
|
||||
__ERR__(__LOG_E__ << "No URI to import.\n", NULL)
|
||||
|
||||
AutoPtr <Geometry> geo(new Geometry);
|
||||
|
||||
// Load file in memory.
|
||||
Array <char> obj;
|
||||
if (!Platform::Get().io->FileLoad(uri, obj))
|
||||
__ERR__(__LOG_E__ << "File '" << uri << "' not found.\n", NULL)
|
||||
|
||||
// Now parse.
|
||||
List <Vector4 *> vtx_list;
|
||||
List <Vector2 *> uv_list;
|
||||
List <ObjPoly *> pol_list;
|
||||
|
||||
bool has_uv = false;
|
||||
const char *pobj = &obj[0], *eobj = pobj + obj.GetSize();
|
||||
|
||||
while (pobj < eobj)
|
||||
{
|
||||
String word(pobj, SkipEntry(pobj, eobj));
|
||||
|
||||
if (word == "v")
|
||||
{
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
float x = 0, y = 0, z = 0;
|
||||
|
||||
x = String::atof(pobj, eobj);
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
y = String::atof(pobj, eobj);
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
z = -String::atof(pobj, eobj);
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
vtx_list.Add(new Vector4(x, y, z));
|
||||
}
|
||||
else if (word == "vt")
|
||||
{
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
float u = 0, v = 0;
|
||||
|
||||
u = String::atof(pobj, eobj);
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
v = String::atof(pobj, eobj);
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
uv_list.Add(new Vector2(u, v));
|
||||
}
|
||||
else if (word == "f")
|
||||
{
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
ObjPoly *pol = new ObjPoly;
|
||||
pol_list.Add(pol);
|
||||
|
||||
const char *eol = RunToEOL(pobj, eobj);
|
||||
while (pobj < eol)
|
||||
{
|
||||
pol->vtx.Add(String::atoi(pobj)); // Index.
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
if (pobj[0] == '/')
|
||||
{
|
||||
pobj++;
|
||||
if (pobj[0] != '/')
|
||||
{
|
||||
has_uv = true;
|
||||
pol->uv.Add(String::atoi(pobj)); // UV index.
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (pobj[0] == '/')
|
||||
{
|
||||
pobj++;
|
||||
pol->nrm.Add(String::atoi(pobj)); // Normal index.
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
pobj = NextEntry(RunToEOL(pobj, eobj), eobj);
|
||||
}
|
||||
|
||||
// Drop OBJ.
|
||||
obj.Free();
|
||||
|
||||
// Transfer vertice.
|
||||
if (geo->vtx.Allocate(vtx_list.GetCount()))
|
||||
{
|
||||
uint cvtx = 0;
|
||||
ListForeachPtr(Vector4 *, v, vtx_list)
|
||||
geo->vtx[cvtx++] = *v;
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate " << vtx_list.GetCount() << " vertices.\n";
|
||||
|
||||
ListDeleteAllPtr(Vector4 *, vtx_list)
|
||||
|
||||
// Transfer polygon.
|
||||
if (geo->pol.Allocate(pol_list.GetCount()))
|
||||
{
|
||||
uint binding_count = 0;
|
||||
ListForeachPtr(ObjPoly *, p, pol_list)
|
||||
binding_count += p->vtx.GetCount();
|
||||
|
||||
geo->binding.Allocate(binding_count);
|
||||
|
||||
Array <Vector2> flat_uv;
|
||||
|
||||
if (has_uv)
|
||||
if (flat_uv.Allocate(binding_count))
|
||||
{
|
||||
geo->uv[0].Allocate(binding_count);
|
||||
|
||||
Vector2 *pflat_uv = &flat_uv[0];
|
||||
ListForeachPtr(Vector2 *, uv, uv_list)
|
||||
*pflat_uv++ = *uv;
|
||||
|
||||
ListDeleteAllPtr(Vector2 *, uv_list)
|
||||
}
|
||||
|
||||
Vector2 *puv = &geo->uv[0][0];
|
||||
|
||||
if (geo->binding)
|
||||
{
|
||||
uint *pbind = &geo->binding[0];
|
||||
|
||||
uint cpol = 0;
|
||||
ListForeachPtr(ObjPoly *, p, pol_list)
|
||||
{
|
||||
Polygon *pol = &geo->pol[cpol];
|
||||
|
||||
pol->vtx_count = (ushort)p->vtx.GetCount();
|
||||
pol->binding = pbind;
|
||||
pol->material = 0;
|
||||
|
||||
for (int v = p->vtx.GetCount(); v > 0; --v)
|
||||
*pbind++ = p->vtx.ObjectAt(v - 1) - 1;
|
||||
|
||||
ListForeachPtr(int, i, p->uv)
|
||||
*puv++ = flat_uv[i - 1];
|
||||
}
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate " << geo->binding.GetCount() << " polygon binding entries.\n";
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate " << geo->pol.GetCount() << " polygons.\n";
|
||||
|
||||
ListDeleteAllPtr(ObjPoly *, pol_list)
|
||||
|
||||
// Load materials.
|
||||
geo->material_table.Allocate(1);
|
||||
geo->material_table[0].name = "Default";
|
||||
|
||||
// Setup defaults.
|
||||
geo->ComputeVertexNormal();
|
||||
|
||||
return geo.Detach();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
80
include/modules/io_archive/io_archive.cpp
Normal file
80
include/modules/io_archive/io_archive.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "io_archive/io_archive.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::IO;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
uint Archive::GetCaps() const
|
||||
{ return CanSeek | CanRead | IsCaseSensitive; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Handle *Archive::Open(const char *uri, Mode mode)
|
||||
{
|
||||
if (mode == ModeRead)
|
||||
if (ArchiveEntry *e = archive.Exists(uri))
|
||||
{
|
||||
AutoPtr <ArchiveHandle> h(new ArchiveHandle(this));
|
||||
if (!h->data.Allocate(e->length) || !archive.FileRead(uri, (void *)h->data.c_ptr()))
|
||||
return NULL;
|
||||
return h.Detach();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void Archive::Close(Handle *) {}
|
||||
bool Archive::Delete(const char *) { return false; }
|
||||
|
||||
size_t Archive::Tell(Handle *h)
|
||||
{
|
||||
if (ArchiveHandle *_h = (ArchiveHandle *)h)
|
||||
return _h->cursor;
|
||||
return (size_t)-1;
|
||||
}
|
||||
size_t Archive::Seek(Handle *h, ptrdiff_t offset, SeekRef seek_ref)
|
||||
{
|
||||
if (ArchiveHandle *_h = (ArchiveHandle *)h)
|
||||
{
|
||||
switch (seek_ref)
|
||||
{
|
||||
case SeekStart:
|
||||
_h->cursor = Types::Clamp <ptrdiff_t> (offset, 0, _h->data.GetSize());
|
||||
break;
|
||||
case SeekCurrent:
|
||||
_h->cursor = Types::Clamp <ptrdiff_t> (_h->cursor + offset, 0, _h->data.GetSize());
|
||||
break;
|
||||
case SeekEnd:
|
||||
_h->cursor = Types::Clamp <ptrdiff_t> (_h->data.GetSize() - offset, 0, _h->data.GetSize());
|
||||
break;
|
||||
}
|
||||
return _h->cursor;
|
||||
}
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
size_t Archive::Read(Handle *h, void *ptr, size_t size)
|
||||
{
|
||||
size_t read_size = 0;
|
||||
if (ArchiveHandle *_h = (ArchiveHandle *)h)
|
||||
{
|
||||
read_size = Types::Min <ptrdiff_t> (size, _h->data.GetSize() - _h->cursor);
|
||||
GS::Memory::Copy(ptr, &_h->data[(int)_h->cursor], read_size);
|
||||
_h->cursor += read_size;
|
||||
}
|
||||
return read_size;
|
||||
}
|
||||
size_t Archive::Write(Handle *, const void *, size_t size)
|
||||
{ return 0; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Archive::Archive(const char *uri, const char *index_uri)
|
||||
{
|
||||
if ((connected = archive.OpenRead(uri, index_uri)) == false)
|
||||
__LOG_E__ << "Failed to connect filesystem to archive '" << uri << "'.\n";
|
||||
}
|
||||
79
include/modules/io_net/io_net_client.cpp
Normal file
79
include/modules/io_net/io_net_client.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "io_net/io_net_client.h"
|
||||
#include "io_net/io_net_client_worker_thread.h"
|
||||
#include "ascii/parser.h"
|
||||
#include "container/nlist.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::IO;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
uint Net::GetCaps() const
|
||||
{ return IsCaseSensitive | CanRead | CanSeek; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Net::QueueTask(NetWorkerBaseTask &task)
|
||||
{
|
||||
if (!worker.QueueTask(task))
|
||||
__ERR__("Net::QueueTask failed.\n", false);
|
||||
|
||||
while (task.processed.Get() == 0) {}
|
||||
return asbool(task.success.Get());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Handle *Net::Open(const char *path, Mode mode)
|
||||
{
|
||||
NetWorkerOpenTask task(path, mode);
|
||||
return QueueTask(task) ? new NetHandle(this, task.handle) : NULL;
|
||||
}
|
||||
void Net::Close(Handle *h)
|
||||
{
|
||||
NetWorkerCloseTask task(((NetHandle *)h)->remote_id);
|
||||
QueueTask(task);
|
||||
}
|
||||
size_t Net::Tell(Handle *h)
|
||||
{
|
||||
NetWorkerTellTask task(((NetHandle *)h)->remote_id);
|
||||
return QueueTask(task) ? task.pos : 0;
|
||||
}
|
||||
size_t Net::Seek(Handle *h, ptrdiff_t offset, SeekRef ref)
|
||||
{
|
||||
NetWorkerSeekTask task(((NetHandle *)h)->remote_id, offset, ref);
|
||||
return QueueTask(task) ? task.pos : 0;
|
||||
}
|
||||
size_t Net::Read(Handle *h, void *data, size_t size)
|
||||
{
|
||||
NetWorkerReadTask task(((NetHandle *)h)->remote_id, data, size);
|
||||
return QueueTask(task) ? task.read_size : 0;
|
||||
}
|
||||
GS::String Net::Hash(const char *uri)
|
||||
{
|
||||
NetWorkerHashTask task(uri);
|
||||
return QueueTask(task) ? task.hash : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Net::IsConnected() const
|
||||
{ return worker.IsConnected(); }
|
||||
bool Net::Connect(const char *ip, int port)
|
||||
{ return worker.Start(ip, port); }
|
||||
void Net::Disconnect()
|
||||
{ worker.Stop(); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NetHandle::~NetHandle()
|
||||
{ GetIOSystem()->Close(this); }
|
||||
//------------------------------------------------------------------------------
|
||||
297
include/modules/io_net/io_net_client_worker_thread.cpp
Normal file
297
include/modules/io_net/io_net_client_worker_thread.cpp
Normal file
@ -0,0 +1,297 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "io_net/io_net_client.h"
|
||||
#include "ascii/parser.h"
|
||||
#include "container/nlist.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::IO;
|
||||
using namespace GS::Threading;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool NetWorkerThread::ProcessOpenTask(NetWorkerOpenTask &task)
|
||||
{
|
||||
if (!server_peer)
|
||||
__ERR__(__LOG_F__ << "No peer.\n", false)
|
||||
if (!SendString(server_peer, String("Open,") << task.path))
|
||||
__ERR__(__LOG_F__ << "SendString failed, server = '" << server_peer << "', task.path = '" << task.path << "'\n", false)
|
||||
|
||||
if (!WaitServerResponse())
|
||||
__ERR__(__LOG_F__ << "WaitServerResponse = false\n", false)
|
||||
|
||||
String answer(response.c_ptr(), response.GetSize());
|
||||
ClearServerResponse();
|
||||
|
||||
StringList args;
|
||||
if (answer.Split(",", args) != 2)
|
||||
__ERR__(__LOG_F__ << "NetWorkerThread Wrong arg count: " << answer << "\n", false)
|
||||
|
||||
if (args[0] != "Success")
|
||||
__ERR__(__LOG_F__ << "args[0] != Success ('" << args[0] << "')\n", false)
|
||||
|
||||
task.handle = args[1].Integer();
|
||||
return true;
|
||||
}
|
||||
bool NetWorkerThread::ProcessCloseTask(NetWorkerCloseTask &task)
|
||||
{
|
||||
if (!server_peer || !SendString(server_peer, String("Close,") << task.handle))
|
||||
return false;
|
||||
|
||||
if (WaitServerResponse()) // FIXME does not even check for success...
|
||||
ClearServerResponse();
|
||||
return true;
|
||||
}
|
||||
bool NetWorkerThread::ProcessSeekTask(NetWorkerSeekTask &task)
|
||||
{
|
||||
String seek_ref;
|
||||
switch (task.seek_ref)
|
||||
{
|
||||
case Base::SeekStart: seek_ref = "Start"; break;
|
||||
case Base::SeekCurrent: seek_ref = "Current"; break;
|
||||
case Base::SeekEnd: seek_ref = "End"; break;
|
||||
}
|
||||
if (!server_peer || !SendString(server_peer, String::Format("Seek,%d,%s,%d", task.offset, seek_ref.c_str(), task.handle)))
|
||||
return false;
|
||||
|
||||
if (!WaitServerResponse())
|
||||
return false;
|
||||
String answer(response.c_ptr(), response.GetSize());
|
||||
ClearServerResponse();
|
||||
|
||||
StringList args;
|
||||
if (answer.Split(",", args) != 2)
|
||||
return false;
|
||||
if (args[0] != "Success")
|
||||
return false;
|
||||
|
||||
task.pos = size_t(args[1].Integer());
|
||||
return true;
|
||||
}
|
||||
bool NetWorkerThread::ProcessTellTask(NetWorkerTellTask &task)
|
||||
{
|
||||
if (!server_peer || !SendString(server_peer, String("Tell,") << task.handle))
|
||||
return false;
|
||||
|
||||
if (!WaitServerResponse())
|
||||
return false;
|
||||
String answer(response.c_ptr(), response.GetSize());
|
||||
ClearServerResponse();
|
||||
|
||||
StringList args;
|
||||
if (answer.Split(",", args) != 2)
|
||||
return false;
|
||||
if (args[0] != "Success")
|
||||
return false;
|
||||
|
||||
task.pos = size_t(args[1].Integer());
|
||||
return true;
|
||||
}
|
||||
bool NetWorkerThread::ProcessReadTask(NetWorkerReadTask &task)
|
||||
{
|
||||
if (!server_peer || !SendString(server_peer, String::Format("Read,%d,%d", task.size, task.handle)))
|
||||
return false;
|
||||
|
||||
if (!WaitServerResponse())
|
||||
return false;
|
||||
|
||||
// Check success.
|
||||
if (Memory::Compare("Success,", response.c_ptr(), 8))
|
||||
return false; // failed
|
||||
|
||||
// Parse size.
|
||||
const char *p_size = response.c_ptr() + 8;
|
||||
const char *e_size = AsciiParser::Find(response.c_ptr() + 8, response.End(), ',');
|
||||
if (e_size == NULL)
|
||||
return false;
|
||||
task.read_size = size_t(String(p_size, e_size).Integer());
|
||||
|
||||
// Get data.
|
||||
const char *p_data = e_size + 1;
|
||||
if (task.read_size != size_t(response.End() - p_data))
|
||||
return false; // assert buffer size and reported size match
|
||||
if (task.read_size > task.size)
|
||||
return false; // prevent buffer overrun
|
||||
|
||||
Memory::Copy(task.data, p_data, task.read_size);
|
||||
|
||||
ClearServerResponse();
|
||||
return true;
|
||||
}
|
||||
bool NetWorkerThread::ProcessHashTask(NetWorkerHashTask &task)
|
||||
{
|
||||
if (!server_peer || !SendString(server_peer, String("Hash,") << task.path))
|
||||
return false;
|
||||
|
||||
if (!WaitServerResponse())
|
||||
return false;
|
||||
|
||||
// Check success.
|
||||
if (Memory::Compare("Success,", response.c_ptr(), 8))
|
||||
return false; // failed
|
||||
|
||||
// Grab hash.
|
||||
task.hash.Set(response.c_ptr() + 8);
|
||||
|
||||
ClearServerResponse();
|
||||
return true;
|
||||
}
|
||||
void NetWorkerThread::ProcessTask(NetWorkerBaseTask &task)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
switch (task.type)
|
||||
{
|
||||
case NetWorkerBaseTask::TypeOpen: success = ProcessOpenTask((NetWorkerOpenTask &)task); break;
|
||||
case NetWorkerBaseTask::TypeClose: success = ProcessCloseTask((NetWorkerCloseTask &)task); break;
|
||||
case NetWorkerBaseTask::TypeSeek: success = ProcessSeekTask((NetWorkerSeekTask &)task); break;
|
||||
case NetWorkerBaseTask::TypeTell: success = ProcessTellTask((NetWorkerTellTask &)task); break;
|
||||
case NetWorkerBaseTask::TypeRead: success = ProcessReadTask((NetWorkerReadTask &)task); break;
|
||||
case NetWorkerBaseTask::TypeHash: success = ProcessHashTask((NetWorkerHashTask &)task); break;
|
||||
}
|
||||
|
||||
// [EJ] Full memory barrier required here.
|
||||
task.success.Set(success ? 1 : 0);
|
||||
task.processed.Set(1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool NetWorkerThread::QueueTask(NetWorkerBaseTask &task)
|
||||
{
|
||||
if (server_peer == NULL)
|
||||
return false; // [EJ] no queue when not connected
|
||||
|
||||
MutexLock lock(&task_mutex);
|
||||
return asbool(task_queue.Add(&task));
|
||||
}
|
||||
bool NetWorkerThread::CancelTask(NetWorkerBaseTask &task)
|
||||
{
|
||||
MutexLock lock(&task_mutex);
|
||||
return asbool(task_queue.Remove(&task));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetWorkerThread::OnPeerConnection(void *peer)
|
||||
{
|
||||
__LOG_V__ << "IO::Net: OnPeerConnection\n";
|
||||
|
||||
if (server_peer || (handshaking != 1)) // already connected
|
||||
{
|
||||
Disconnect(peer);
|
||||
return;
|
||||
}
|
||||
|
||||
SetPeerTimeout(peer, TimeoutVeryLong);
|
||||
SendString(peer, "RequestIOAccess");
|
||||
|
||||
++handshaking;
|
||||
}
|
||||
void NetWorkerThread::OnPacketReceived(void *peer, const void *data, size_t size)
|
||||
{
|
||||
// __LOG_V__ << "IO::Net: Packet received, handshaking = " << handshaking << ", data: " << String((const char *)data, (const char *)data + size) << "\n";
|
||||
|
||||
if (handshaking == 2)
|
||||
{
|
||||
if ((size == 8) && !GS::Memory::Compare(data, "Granted", size))
|
||||
{
|
||||
server_peer = peer;
|
||||
++handshaking;
|
||||
}
|
||||
else
|
||||
Disconnect(peer);
|
||||
}
|
||||
else
|
||||
if (server_peer == peer)
|
||||
ProcessIOPacket(data, size);
|
||||
}
|
||||
void NetWorkerThread::OnConnectionClosed(void *peer)
|
||||
{
|
||||
if (server_peer == peer)
|
||||
server_peer = NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetWorkerThread::ProcessIOPacket(const void *data, size_t size)
|
||||
{
|
||||
if (response.Allocate(size))
|
||||
Memory::Copy(response.c_ptr(), data, size);
|
||||
}
|
||||
bool NetWorkerThread::WaitServerResponse()
|
||||
{
|
||||
while (response.GetSize() == 0)
|
||||
{
|
||||
if (server_peer == NULL)
|
||||
return false;
|
||||
UpdateHost();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void NetWorkerThread::ClearServerResponse()
|
||||
{ response.Free(); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetWorkerThread::Execute()
|
||||
{
|
||||
Thread::SetName("GS::IO::NetWorkerThread");
|
||||
|
||||
handshaking = 1;
|
||||
|
||||
__LOG_V__ << "IO::Net - Client worker thread connecting to " << ip << " port " << port << ".\n";
|
||||
if (!OpenClient(ip, port))
|
||||
__ERRRAW__(__LOG_E__ << "Connection failed.\n");
|
||||
|
||||
__LOG_V__ << "IO::Net - Entering file server loop...\n";
|
||||
for (running.Set(1); running.Get() != 2; )
|
||||
{
|
||||
UpdateHost();
|
||||
|
||||
if (server_peer != NULL)
|
||||
{
|
||||
MutexLock lock(&task_mutex);
|
||||
while (NetWorkerBaseTask *task = task_queue.GetCount() > 0 ? task_queue.GetRoot()->Object() : NULL)
|
||||
{
|
||||
task_queue.RemoveAt(0);
|
||||
ProcessTask(*task);
|
||||
}
|
||||
|
||||
if (server_peer == NULL) // [EJ] if connection was lost during this run, drop all pending tasks.
|
||||
task_queue.Clear();
|
||||
}
|
||||
|
||||
Platform::Get().Sleep(1);
|
||||
}
|
||||
|
||||
handshaking = 0;
|
||||
|
||||
__LOG_V__ << "IO::Net - Client worker thread exiting.\n";
|
||||
running.Set(0);
|
||||
}
|
||||
bool NetWorkerThread::Start(const char *_ip, int _port)
|
||||
{
|
||||
ip = _ip;
|
||||
port = _port;
|
||||
return Thread::Start();
|
||||
}
|
||||
void NetWorkerThread::Stop()
|
||||
{
|
||||
if (running.Get() != 0)
|
||||
{
|
||||
running.Set(2);
|
||||
while (running.Get() != 0); // spinlock
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NetWorkerThread::NetWorkerThread() : server_peer(0), handshaking(0) {}
|
||||
//------------------------------------------------------------------------------
|
||||
325
include/modules/io_net/io_net_server.cpp
Normal file
325
include/modules/io_net/io_net_server.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "io_net/io_net_server.h"
|
||||
#include "metafile/nml.h"
|
||||
#include "async/task_loop.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::IO;
|
||||
|
||||
// #define VERBOSE_LOG
|
||||
|
||||
|
||||
// @FIXME Rewrite communication with the controller thread using AsyncCallQueue.
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NetServer::Client *NetServer::GetClient(void *peer)
|
||||
{
|
||||
ListForeachPtr(Client *, client, clients)
|
||||
if (client->peer == peer)
|
||||
return client;
|
||||
return NULL;
|
||||
}
|
||||
int NetServer::GetClientFreeHandleIndex(const Client &client) const
|
||||
{
|
||||
int free_id = 0;
|
||||
ListForeachPtr(ClientHandleInfo *, i, client.handles)
|
||||
if (i->id >= free_id)
|
||||
free_id = i->id + 1;
|
||||
return free_id;
|
||||
}
|
||||
Handle *NetServer::GetClientHandle(const Client &client, int id) const
|
||||
{
|
||||
ListForeachPtr(ClientHandleInfo *, i, client.handles)
|
||||
if (i->id == id)
|
||||
return i->handle;
|
||||
return NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool NetServer::ProcessCloseCommand(Client &client, GS::StringList &args)
|
||||
// Close,handle_id
|
||||
{
|
||||
if (args.GetCount() != 2)
|
||||
return false;
|
||||
|
||||
int id = args[1].Integer();
|
||||
|
||||
ClientHandleInfo *hi = NULL;
|
||||
ListForeachPtr(ClientHandleInfo *, i, client.handles)
|
||||
if (i->id == id)
|
||||
{
|
||||
hi = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hi == NULL)
|
||||
return false;
|
||||
|
||||
client.handles.Remove(hi);
|
||||
|
||||
#ifdef VERBOSE_LOG
|
||||
__LOG__ << "IO::NetServer: Close handle " << id << " (client total: " << client.handles.GetCount() << ").\n";
|
||||
#endif
|
||||
return SendString(client.peer, "Success");
|
||||
}
|
||||
bool NetServer::ProcessReadCommand(Client &client, GS::StringList &args)
|
||||
// Read,size,handle_id
|
||||
{
|
||||
if (args.GetCount() != 3)
|
||||
return false;
|
||||
|
||||
Handle *h = GetClientHandle(client, args[2].Integer());
|
||||
if (h == NULL)
|
||||
return false;
|
||||
|
||||
// Read data.
|
||||
size_t size = size_t(args[1].Integer());
|
||||
Array <char> data(size);
|
||||
size_t read_size = h->Read((void *)data, size);
|
||||
|
||||
// Format answer data (FIXME two allocations are not required for this).
|
||||
String answer = String::Format("Success,%d,", read_size);
|
||||
|
||||
Array <char> answer_data(answer.Len() + read_size);
|
||||
Memory::Copy(answer_data.c_ptr(), answer.c_str(), answer.Len());
|
||||
Memory::Copy(answer_data.c_ptr() + answer.Len(), data.c_ptr(), read_size);
|
||||
|
||||
return Send(client.peer, (void *)answer_data.c_ptr(), answer_data.GetSize());
|
||||
}
|
||||
bool NetServer::ProcessSeekCommand(Client &client, GS::StringList &args)
|
||||
// Seek,offset_from_start,ref,handle_id
|
||||
{
|
||||
if (args.GetCount() != 4)
|
||||
return false;
|
||||
|
||||
Handle *h = GetClientHandle(client, args[3].Integer());
|
||||
if (h == NULL)
|
||||
return false;
|
||||
|
||||
ptrdiff_t offset = ptrdiff_t(args[1].Integer());
|
||||
|
||||
Base::SeekRef seek_ref;
|
||||
if (args[2] == "Start")
|
||||
seek_ref = Base::SeekStart;
|
||||
else if (args[2] == "Current")
|
||||
seek_ref = Base::SeekCurrent;
|
||||
else if (args[2] == "End")
|
||||
seek_ref = Base::SeekEnd;
|
||||
else
|
||||
return false;
|
||||
|
||||
size_t r = h->Seek(offset, seek_ref);
|
||||
return SendString(client.peer, String::Format("Success,%d", r));
|
||||
}
|
||||
bool NetServer::ProcessTellCommand(Client &client, GS::StringList &args)
|
||||
// Tell,handle_id
|
||||
{
|
||||
if (args.GetCount() != 2)
|
||||
return false;
|
||||
|
||||
Handle *h = GetClientHandle(client, args[1].Integer());
|
||||
if (h == NULL)
|
||||
return false;
|
||||
|
||||
return SendString(client.peer, String::Format("Success,%d", h->Tell()));
|
||||
}
|
||||
bool NetServer::ProcessOpenCommand(Client &client, GS::StringList &args)
|
||||
// Open,path
|
||||
{
|
||||
if (args.GetCount() != 2)
|
||||
__ERR__(__LOG_E__ << "NetServer::ProcessOpenCommand(): incorrect argument count.\n", false)
|
||||
|
||||
int index = GetClientFreeHandleIndex(client);
|
||||
|
||||
AutoPtr <ClientHandleInfo> i(new ClientHandleInfo);
|
||||
i->id = index;
|
||||
i->name = args[1];
|
||||
i->handle = basefs->Open(i->name);
|
||||
if (i->handle.IsNull())
|
||||
return false; // __ERR__(__LOG_E__ << "NetServer::ProcessOpenCommand(): failed to open '" << i->name << "' on base filesystem.\n", false)
|
||||
|
||||
client.handles.Add(i.Detach());
|
||||
|
||||
#ifdef VERBOSE_LOG
|
||||
__LOG__ << "IO::NetServer: Open handle '" << args[1] << "' => " << index << " (client total: " << client.handles.GetCount() << ").\n";
|
||||
#endif
|
||||
return SendString(client.peer, String::Format("Success,%d", index));
|
||||
}
|
||||
bool NetServer::ProcessHashCommand(Client &client, GS::StringList &args)
|
||||
// Hash,path
|
||||
{
|
||||
if (args.GetCount() != 2)
|
||||
return false;
|
||||
|
||||
String hash = basefs->Hash(args[1]);
|
||||
if (hash.IsEmpty())
|
||||
return false;
|
||||
|
||||
return SendString(client.peer, String::Format("Success,%s", hash.c_str()));
|
||||
}
|
||||
bool NetServer::ProcessClientRequest(Client &client, const GS::String &data)
|
||||
{
|
||||
StringList args;
|
||||
data.Split(",", args);
|
||||
|
||||
bool r = false;
|
||||
|
||||
// Command dispatch.
|
||||
if (args[0] == "Open")
|
||||
r = ProcessOpenCommand(client, args);
|
||||
else if (args[0] == "Seek")
|
||||
r = ProcessSeekCommand(client, args);
|
||||
else if (args[0] == "Tell")
|
||||
r = ProcessTellCommand(client, args);
|
||||
else if (args[0] == "Read")
|
||||
r = ProcessReadCommand(client, args);
|
||||
else if (args[0] == "Close")
|
||||
r = ProcessCloseCommand(client, args);
|
||||
else if (args[0] == "Hash")
|
||||
r = ProcessHashCommand(client, args);
|
||||
|
||||
if (!r)
|
||||
SendString(client.peer, "Failed");
|
||||
return r;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetServer::GetStatistics(Statistics &stats)
|
||||
{
|
||||
Time t = Platform::Get().GetTime();
|
||||
|
||||
stats.connected = asbool(clients.GetCount());
|
||||
|
||||
Network::Enet::Statistics enet_stats;
|
||||
Network::Enet::GetStatistics(enet_stats);
|
||||
|
||||
if ((t - bandwidth_measure.time).toSec() > 2)
|
||||
{
|
||||
bandwidth = int((enet_stats.sent_data - bandwidth_measure.value) / (t - bandwidth_measure.time).toSec());
|
||||
|
||||
bandwidth_measure.time = t;
|
||||
bandwidth_measure.value = enet_stats.sent_data;
|
||||
}
|
||||
|
||||
stats.sent_data = enet_stats.sent_data;
|
||||
stats.bandwidth = bandwidth;
|
||||
|
||||
stats.packet_loss = 0;
|
||||
if (clients.GetCount() > 0)
|
||||
{
|
||||
ListForeachPtr(Client *, client, clients)
|
||||
stats.packet_loss += GetPeerPacketLossRatio(client->peer);
|
||||
stats.packet_loss /= clients.GetCount();
|
||||
}
|
||||
|
||||
// Handle statistics.
|
||||
int handle_count = 0;
|
||||
ListForeachPtr(Client *, client, clients)
|
||||
handle_count += client->handles.GetCount();
|
||||
|
||||
if (stats.handles.Allocate(handle_count))
|
||||
{
|
||||
handle_count = 0;
|
||||
ListForeachPtr(Client *, client, clients)
|
||||
ListForeachPtr(ClientHandleInfo *, i, client->handles)
|
||||
{
|
||||
Statistics::Handle *h = &stats.handles[handle_count++];
|
||||
h->name = i->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetServer::OnPeerConnection(void *peer)
|
||||
{
|
||||
__LOG_H__ << "IO::NetServer: OnPeerConnection\n";
|
||||
|
||||
__ASSERT__(GetClient(peer) == NULL);
|
||||
clients.Add(new Client(peer));
|
||||
|
||||
SetPeerTimeout(peer, TimeoutVeryLong);
|
||||
}
|
||||
void NetServer::OnPacketReceived(void *peer, const void *data, size_t size)
|
||||
{
|
||||
Client *client = GetClient(peer);
|
||||
__ASSERT__(client != NULL);
|
||||
|
||||
if (size > 512)
|
||||
{
|
||||
SendString(peer, "DataLengthError");
|
||||
return; // invalid
|
||||
}
|
||||
|
||||
String command((char *)data, (char *)data + size);
|
||||
|
||||
if (client->handshake_step == -1)
|
||||
ProcessClientRequest(*client, command);
|
||||
|
||||
else
|
||||
{
|
||||
switch (client->handshake_step)
|
||||
{
|
||||
case 0:
|
||||
if (command == "RequestIOAccess")
|
||||
{
|
||||
__LOG_V__ << "Granting client access.\n";
|
||||
client->handshake_step = -1;
|
||||
|
||||
SendString(peer, "Granted");
|
||||
}
|
||||
else
|
||||
Disconnect(peer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void NetServer::OnConnectionClosed(void *peer)
|
||||
{
|
||||
__LOG_H__ << "IO::NetServer: OnConnectionClosed\n";
|
||||
|
||||
Client *client = GetClient(peer);
|
||||
__ASSERT__(client != NULL);
|
||||
clients.Remove(client);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool NetServer::Start(const char *ip, int port)
|
||||
{
|
||||
__LOG_H__ << "IO::NetServer: Starting on " << ip << " port " << port << ".\n";
|
||||
return OpenServer(ip, port);
|
||||
}
|
||||
void NetServer::Stop()
|
||||
{
|
||||
__LOG_H__ << "IO::NetServer: Shutting down.\n";
|
||||
|
||||
// Disconnect all clients.
|
||||
ListForeachPtr(Client *, c, clients)
|
||||
Disconnect(c->peer);
|
||||
|
||||
StartTaskLoop(clients.GetCount() > 0, 2000)
|
||||
{
|
||||
UpdateHost();
|
||||
Platform::Get().Sleep(1);
|
||||
}
|
||||
EndTaskLoop
|
||||
|
||||
Close();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NetServer::NetServer(Base *fs) : basefs(fs), bandwidth(0)
|
||||
{}
|
||||
NetServer::~NetServer()
|
||||
{ Stop(); }
|
||||
//------------------------------------------------------------------------------
|
||||
76
include/modules/io_net/io_net_server_thread.cpp
Normal file
76
include/modules/io_net/io_net_server_thread.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "io_net/io_net_server_thread.h"
|
||||
#include "filesystem/io_cfile.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::IO;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetServerThread::Execute()
|
||||
{
|
||||
{
|
||||
Threading::MutexLock lock(&server_mutex);
|
||||
server = new NetServer(basefs);
|
||||
}
|
||||
|
||||
if (server->Start(ip.c_str(), port))
|
||||
for (state.Set(1); state.Get() != 2; )
|
||||
{
|
||||
{
|
||||
Threading::MutexLock lock(&server_mutex);
|
||||
server->UpdateHost();
|
||||
}
|
||||
Platform::Get().Sleep(1);
|
||||
}
|
||||
|
||||
{
|
||||
Threading::MutexLock lock(&server_mutex);
|
||||
server = NULL;
|
||||
}
|
||||
state.Set(0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool NetServerThread::Start(const char *_ip, int _port)
|
||||
{
|
||||
ip = _ip;
|
||||
port = _port;
|
||||
|
||||
if (!Thread::Start())
|
||||
return false;
|
||||
|
||||
while (state.Get() == 0)
|
||||
;
|
||||
|
||||
return asbool(state.Get() != -1);
|
||||
}
|
||||
void NetServerThread::Stop()
|
||||
{
|
||||
state.Set(2);
|
||||
while (state.Get() != 0); // spinlock
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void NetServerThread::GetStatistics(NetServer::Statistics &stats)
|
||||
{
|
||||
Threading::MutexLock lock(&server_mutex);
|
||||
if (server.IsValid())
|
||||
server->GetStatistics(stats);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NetServerThread::~NetServerThread()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
211
include/modules/io_zip/io_zip.cpp
Normal file
211
include/modules/io_zip/io_zip.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
/*------------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "io_zip/io_zip.h"
|
||||
#include "unzip.h"
|
||||
#include "filesystem/io_handle_segment.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::IO;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// I/O wrapper for unzip (allows archive access from various I/O systems).
|
||||
static voidpf Zip_open_file_func(voidpf opaque, const char *filename, int mode)
|
||||
{
|
||||
__LOG__ << "ZipOpenFileFunc(); filename: " << filename << ", mode: " << mode << ".\n";
|
||||
if (mode & ZLIB_FILEFUNC_MODE_READ)
|
||||
return GS::Platform::Get().io->Open(filename);
|
||||
if (mode & ZLIB_FILEFUNC_MODE_WRITE)
|
||||
return GS::Platform::Get().io->Open(filename, ModeWrite);
|
||||
return NULL;
|
||||
}
|
||||
static uLong Zip_read_file_func(voidpf opaque, voidpf stream, void *buf, uLong size)
|
||||
{ return ((Handle *)stream)->Read(buf, size); }
|
||||
static uLong Zip_write_file_func(voidpf opaque, voidpf stream, const void *buf, uLong size)
|
||||
{ return ((Handle *)stream)->Write(buf, size); }
|
||||
static int Zip_close_file_func(voidpf opaque, voidpf stream)
|
||||
{
|
||||
__LOG__ << "ZipCloseFileFunc();\n";
|
||||
delete ((Handle *)stream);
|
||||
return UNZ_OK;
|
||||
}
|
||||
static int Zip_testerror_file_func(voidpf opaque, voidpf stream)
|
||||
{ return UNZ_OK; }
|
||||
|
||||
static long Zip_tell_file_func(voidpf opaque, voidpf stream)
|
||||
{ return ((Handle *)stream)->Tell(); }
|
||||
static long Zip_seek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin)
|
||||
{
|
||||
static Base::SeekRef ref[] = { Base::SeekStart, Base::SeekCurrent, Base::SeekEnd };
|
||||
return ((Handle *)stream)->Seek(offset, ref[origin]) == -1 ? -1 : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static zlib_filefunc_def Zip_filefunc =
|
||||
{ Zip_open_file_func, Zip_read_file_func, Zip_write_file_func, Zip_tell_file_func, Zip_seek_file_func, Zip_close_file_func, Zip_testerror_file_func, 0 };
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Zip::SetArchive(const char *uri, const char *pass)
|
||||
{
|
||||
if (zfile)
|
||||
unzClose(zfile);
|
||||
zfile = NULL;
|
||||
|
||||
if (!uri)
|
||||
return true;
|
||||
|
||||
__LOG_H__ << "Zip::SetArchive() connect to archive '" << uri << "', password: " << (pass ? pass : "(empty)") << ".\n";
|
||||
|
||||
password = pass;
|
||||
return uri ? (zfile = unzOpen2(uri, &Zip_filefunc)) != NULL : false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
uint Zip::GetCaps() const
|
||||
{ return CanRead | CanSeek| IsCaseSensitive; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Handle *Zip::Open(const char *path, Mode mode)
|
||||
{
|
||||
if (!zfile)
|
||||
__ERR__(__LOG_E__ << "Cannot open file with no archive support.\n", NULL)
|
||||
|
||||
if (mode == ModeWrite)
|
||||
return NULL; // unsupported
|
||||
|
||||
/*
|
||||
Query the memory file system so that multiple accesses to the same
|
||||
compressed file will share a single uncompressed memory buffer.
|
||||
*/
|
||||
bool is_memory_handle = false;
|
||||
Handle *h = memfs->Open(path, mode);
|
||||
|
||||
if (!h)
|
||||
if (unzLocateFile(zfile, path, 1) == UNZ_OK) // case-sensitive
|
||||
{
|
||||
// Get file info.
|
||||
unz_file_info info;
|
||||
unzGetCurrentFileInfo(zfile, &info, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
if (info.compression_method == 0)
|
||||
{
|
||||
unzOpenCurrentFile(zfile);
|
||||
size_t offset = (size_t)unzGetCurrentFileZStreamPos64(zfile);
|
||||
unzCloseCurrentFile(zfile);
|
||||
|
||||
__LOG__ << "Mapping zip segment to '" << path << "' @" << int(offset) << "\n";
|
||||
Handle *zh = (Handle *)unzGetFileStream(zfile);
|
||||
h = new HandleSegment(zh, offset, info.uncompressed_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
__LOG__ << "Mapping unzipped '" << path << "' to memory...\n";
|
||||
|
||||
// Load the whole file into memory.
|
||||
Array <char> data(info.uncompressed_size, Alloc::Filesystem);
|
||||
if (data.GetSize() != info.uncompressed_size)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate decompression space for '" << path << "'.\n", NULL)
|
||||
|
||||
int r = password.IsEmpty() ? unzOpenCurrentFile(zfile) : unzOpenCurrentFilePassword(zfile, password);
|
||||
if (r != UNZ_OK)
|
||||
__ERR__(__LOG_E__ << "Failed to open file '" << path << "'.\n", NULL)
|
||||
if (unzReadCurrentFile(zfile, (voidp)data.c_ptr(), info.uncompressed_size) != (int)info.uncompressed_size)
|
||||
__ERR__(__LOG_E__ << "Failed to read file '" << path << "'.\n", NULL)
|
||||
unzCloseCurrentFile(zfile);
|
||||
|
||||
// Write to the support I/O memory filesystem.
|
||||
AutoPtr <Handle> wh(memfs->Open(path, ModeWrite));
|
||||
if (wh.IsValid())
|
||||
wh->Write(data.c_ptr(), data.GetSize());
|
||||
|
||||
// Open memory based uncompressed file.
|
||||
h = memfs->Open(path, mode);
|
||||
is_memory_handle = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (h)
|
||||
if (ZipHandle *z = new ZipHandle(this))
|
||||
{
|
||||
// Wrap memory I/O handle.
|
||||
if (is_memory_handle)
|
||||
{
|
||||
// Increase refcount for this file.
|
||||
Pair <String, int> *p = refc_map.Get(path);
|
||||
if (!p)
|
||||
p = refc_map.Add(path, 0);
|
||||
++p->value;
|
||||
|
||||
z->p = p;
|
||||
}
|
||||
|
||||
z->h = h;
|
||||
return z;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
void Zip::Close(Handle *h)
|
||||
{
|
||||
if (ZipHandle *z = (ZipHandle *)h)
|
||||
{
|
||||
if (z->p)
|
||||
{
|
||||
// If refcount for this entry reaches 0, drop it from the support I/O.
|
||||
if (--z->p->value == 0)
|
||||
{
|
||||
memfs->Delete(z->p->key);
|
||||
refc_map.Delete(z->p);
|
||||
}
|
||||
z->p = NULL;
|
||||
}
|
||||
z->h = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool Zip::Delete(const char *uri)
|
||||
{ return false; }
|
||||
|
||||
size_t Zip::Seek(Handle *h, ptrdiff_t offset, SeekRef ref)
|
||||
{
|
||||
if (ZipHandle *z = (ZipHandle *)h)
|
||||
return z->h->Seek(offset, ref);
|
||||
return (size_t)-1;
|
||||
}
|
||||
size_t Zip::Tell(Handle *h)
|
||||
{
|
||||
if (ZipHandle *z = (ZipHandle *)h)
|
||||
return z->h->Tell();
|
||||
return (size_t)-1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
size_t Zip::Read(Handle *h, void *b, size_t size)
|
||||
{
|
||||
if (ZipHandle *z = (ZipHandle *)h)
|
||||
return z->h->Read(b, size);
|
||||
return 0;
|
||||
}
|
||||
size_t Zip::Write(Handle *h, const void *b, size_t size)
|
||||
{ return 0; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Zip::Zip(const char *uri, const char *password)
|
||||
{
|
||||
zfile = NULL;
|
||||
memfs = new Memory;
|
||||
SetArchive(uri, password);
|
||||
}
|
||||
Zip::~Zip()
|
||||
{ SetArchive(NULL, NULL); }
|
||||
//------------------------------------------------------------------------------
|
||||
251
include/modules/nav_detour/navmesh.cpp
Normal file
251
include/modules/nav_detour/navmesh.cpp
Normal file
@ -0,0 +1,251 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "nav_detour/navmesh.h"
|
||||
#include "core/geometry.h"
|
||||
#include "Recast.h"
|
||||
#include "DetourNavMeshQuery.h"
|
||||
#include "DetourNavMeshBuilder.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::Core;
|
||||
using namespace GS::Nav;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Mesh::Build(const Geometry *geo, const BuildConfig &cfg)
|
||||
{
|
||||
// Convert geometry to triangle.
|
||||
uint nverts = geo->vtx.GetCount();
|
||||
|
||||
Array <float> verts(nverts);
|
||||
if (float *pverts = verts.c_ptr())
|
||||
for (uint n = 0; n < nverts; ++n)
|
||||
{
|
||||
*pverts++ = geo->vtx[n][0];
|
||||
*pverts++ = geo->vtx[n][1];
|
||||
*pverts++ = geo->vtx[n][2];
|
||||
}
|
||||
|
||||
uint ntris = geo->GetTriangleCount();
|
||||
|
||||
Array <int> tris(ntris * 3);
|
||||
if (int *ptris = tris.c_ptr())
|
||||
for (uint n = 0; n < geo->pol.GetCount(); ++n)
|
||||
{
|
||||
Polygon &p = geo->pol[n];
|
||||
for (int i = 1; i < (p.vtx_count - 1); ++i)
|
||||
{
|
||||
*ptris++ = p.binding[0];
|
||||
*ptris++ = p.binding[i];
|
||||
*ptris++ = p.binding[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// Init build configuration from GUI
|
||||
rcConfig m_cfg;
|
||||
|
||||
m_cfg.cs = 0.5f; // Cell size.
|
||||
m_cfg.ch = 0.2f; // Cell height.
|
||||
m_cfg.walkableSlopeAngle = 40.f; // Max slope.
|
||||
m_cfg.walkableHeight = (int)Math::Ceil(cfg.agent.height / m_cfg.ch);
|
||||
m_cfg.walkableClimb = (int)Math::Floor(cfg.agent.max_climb / m_cfg.ch);
|
||||
m_cfg.walkableRadius = (int)Math::Ceil(cfg.agent.radius / m_cfg.cs);
|
||||
|
||||
/*
|
||||
m_cfg.maxEdgeLen = (int)(m_edgeMaxLen / m_cellSize);
|
||||
m_cfg.maxSimplificationError = m_edgeMaxError;
|
||||
m_cfg.minRegionArea = (int)rcSqr(m_regionMinSize); // Note: area = size*size
|
||||
m_cfg.mergeRegionArea = (int)rcSqr(m_regionMergeSize); // Note: area = size*size
|
||||
m_cfg.maxVertsPerPoly = (int)m_vertsPerPoly;
|
||||
m_cfg.detailSampleDist = m_detailSampleDist < 0.9f ? 0 : m_cellSize * m_detailSampleDist;
|
||||
m_cfg.detailSampleMaxError = m_cellHeight * m_detailSampleMaxError;
|
||||
*/
|
||||
/*
|
||||
Set the area where the navigation will be build.
|
||||
Here the bounds of the input mesh are used, but the area could be
|
||||
specified by an user defined box, etc.
|
||||
*/
|
||||
|
||||
MinMax mm = geo->ComputeMinMax();
|
||||
rcVcopy(m_cfg.bmin, &mm.mn.x);
|
||||
rcVcopy(m_cfg.bmax, &mm.mx.x);
|
||||
rcCalcGridSize(m_cfg.bmin, m_cfg.bmax, m_cfg.cs, &m_cfg.width, &m_cfg.height);
|
||||
|
||||
// Allocate voxel heightfield where we rasterize our input data to.
|
||||
AutoPtr <rcHeightfield> solid(rcAllocHeightfield());
|
||||
if (solid.IsNull())
|
||||
__ERR__(__LOG_E__ << "Failed to allocate heightfield.\n", false)
|
||||
|
||||
rcContext ctx;
|
||||
if (!rcCreateHeightfield(&ctx, *solid, m_cfg.width, m_cfg.height, m_cfg.bmin, m_cfg.bmax, m_cfg.cs, m_cfg.ch))
|
||||
__ERR__(__LOG_E__ << "Failed to create heightfield.\n", false)
|
||||
|
||||
/*
|
||||
Allocate array that can hold triangle area types.
|
||||
If you have multiple meshes you need to process, allocate an array which
|
||||
can hold the max number of triangles you need to process.
|
||||
*/
|
||||
Array <unsigned char> triareas(ntris);
|
||||
if (triareas.IsNull())
|
||||
__ERR__(__LOG_E__ << "Failed to allocate triangle areas.\n", false)
|
||||
|
||||
/*
|
||||
Find triangles which are walkable based on their slope and rasterize
|
||||
them. If your input data is multiple meshes, you can transform them
|
||||
here, calculate the are type for each of the meshes and rasterize them.
|
||||
*/
|
||||
Memory::Set(triareas, 0, ntris * sizeof(unsigned char));
|
||||
rcMarkWalkableTriangles(&ctx, m_cfg.walkableSlopeAngle, verts, nverts, tris, ntris, triareas);
|
||||
rcRasterizeTriangles(&ctx, verts, nverts, tris, triareas, ntris, *solid, m_cfg.walkableClimb);
|
||||
|
||||
triareas.Free();
|
||||
|
||||
/*
|
||||
Once all geometry is rasterized, we do initial pass of filtering to
|
||||
remove unwanted overhangs caused by the conservative rasterization
|
||||
as well as filter spans where the character cannot possibly stand.
|
||||
*/
|
||||
rcFilterLowHangingWalkableObstacles(&ctx, m_cfg.walkableClimb, *solid);
|
||||
rcFilterLedgeSpans(&ctx, m_cfg.walkableHeight, m_cfg.walkableClimb, *solid);
|
||||
rcFilterWalkableLowHeightSpans(&ctx, m_cfg.walkableHeight, *solid);
|
||||
|
||||
/*
|
||||
Compact the heightfield so that it is faster to handle from now on.
|
||||
This will result more cache coherent data as well as the neighbours
|
||||
between walkable cells will be calculated.
|
||||
*/
|
||||
rcCompactHeightfield *chf = rcAllocCompactHeightfield();
|
||||
if (!chf)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate compact heightfield.\n", false)
|
||||
if (!rcBuildCompactHeightfield(&ctx, m_cfg.walkableHeight, m_cfg.walkableClimb, *solid, *chf))
|
||||
__ERR__(__LOG_E__ << "Failed to build compact heightfield.\n", false)
|
||||
|
||||
solid = NULL;
|
||||
|
||||
// Erode the walkable area by agent radius.
|
||||
if (!rcErodeWalkableArea(&ctx, m_cfg.walkableRadius, *chf))
|
||||
__ERR__(__LOG_E__ << "Failed to erode walkable area.\n", false)
|
||||
|
||||
// (Optional) Mark areas.
|
||||
/*
|
||||
const ConvexVolume *vols = m_geom->getConvexVolumes();
|
||||
for (int i = 0; i < m_geom->getConvexVolumeCount(); ++i)
|
||||
rcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned char)vols[i].area, *m_chf);
|
||||
*/
|
||||
// Prepare for region partitioning, by calculating distance field along the walkable surface.
|
||||
if (!rcBuildDistanceField(&ctx, *chf))
|
||||
__ERR__(__LOG_E__ << "Failed to build distance fields.\n", false)
|
||||
|
||||
// Partition the walkable surface into simple regions without holes.
|
||||
if (!rcBuildRegions(&ctx, *chf, 0, m_cfg.minRegionArea, m_cfg.mergeRegionArea))
|
||||
__ERR__(__LOG_E__ << "Failed to build regions.\n", false)
|
||||
|
||||
// Create contours.
|
||||
rcContourSet *cset = rcAllocContourSet();
|
||||
if (!cset)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate contour set.\n", false)
|
||||
if (!rcBuildContours(&ctx, *chf, m_cfg.maxSimplificationError, m_cfg.maxEdgeLen, *cset))
|
||||
__ERR__(__LOG_E__ << "Failed to create contour set.\n", false)
|
||||
|
||||
// Build polygon navmesh from the contours.
|
||||
rcPolyMesh *pmesh = rcAllocPolyMesh();
|
||||
if (!pmesh)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate navmesh.\n", false)
|
||||
if (!rcBuildPolyMesh(&ctx, *cset, m_cfg.maxVertsPerPoly, *pmesh))
|
||||
__ERR__(__LOG_E__ << "Failed to build navmesh.\n", false)
|
||||
|
||||
rcPolyMeshDetail *dmesh = rcAllocPolyMeshDetail();
|
||||
if (!dmesh)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate detail mesh.\n", false)
|
||||
if (!rcBuildPolyMeshDetail(&ctx, *pmesh, *chf, m_cfg.detailSampleDist, m_cfg.detailSampleMaxError, *dmesh))
|
||||
__ERR__(__LOG_E__ << "Failed to build detail mesh.\n", false)
|
||||
|
||||
rcFreeCompactHeightfield(chf);
|
||||
chf = 0;
|
||||
rcFreeContourSet(cset);
|
||||
cset = 0;
|
||||
|
||||
// The GUI may allow more max points per polygon than Detour can handle.
|
||||
// Only build the detour navmesh if we do not exceed the limit.
|
||||
if (m_cfg.maxVertsPerPoly <= DT_VERTS_PER_POLYGON)
|
||||
{
|
||||
// Update poly flags from areas.
|
||||
/*
|
||||
for (int i = 0; i < pmesh->npolys; ++i)
|
||||
{
|
||||
if (pmesh->areas[i] == RC_WALKABLE_AREA)
|
||||
pmesh->areas[i] = SAMPLE_POLYAREA_GROUND;
|
||||
|
||||
if (pmesh->areas[i] == SAMPLE_POLYAREA_GROUND || pmesh->areas[i] == SAMPLE_POLYAREA_GRASS || pmesh->areas[i] == SAMPLE_POLYAREA_ROAD)
|
||||
pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK;
|
||||
|
||||
else if (pmesh->areas[i] == SAMPLE_POLYAREA_WATER)
|
||||
pmesh->flags[i] = SAMPLE_POLYFLAGS_SWIM;
|
||||
|
||||
else if (pmesh->areas[i] == SAMPLE_POLYAREA_DOOR)
|
||||
pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK | SAMPLE_POLYFLAGS_DOOR;
|
||||
}
|
||||
*/
|
||||
dtNavMeshCreateParams params;
|
||||
Memory::Set(¶ms, 0, sizeof(params));
|
||||
params.verts = pmesh->verts;
|
||||
params.vertCount = pmesh->nverts;
|
||||
params.polys = pmesh->polys;
|
||||
params.polyAreas = pmesh->areas;
|
||||
params.polyFlags = pmesh->flags;
|
||||
params.polyCount = pmesh->npolys;
|
||||
params.nvp = pmesh->nvp;
|
||||
params.detailMeshes = dmesh->meshes;
|
||||
params.detailVerts = dmesh->verts;
|
||||
params.detailVertsCount = dmesh->nverts;
|
||||
params.detailTris = dmesh->tris;
|
||||
params.detailTriCount = dmesh->ntris;
|
||||
/*
|
||||
params.offMeshConVerts = m_geom->getOffMeshConnectionVerts();
|
||||
params.offMeshConRad = m_geom->getOffMeshConnectionRads();
|
||||
params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
|
||||
params.offMeshConAreas = m_geom->getOffMeshConnectionAreas();
|
||||
params.offMeshConFlags = m_geom->getOffMeshConnectionFlags();
|
||||
params.offMeshConUserID = m_geom->getOffMeshConnectionId();
|
||||
params.offMeshConCount = m_geom->getOffMeshConnectionCount();
|
||||
*/
|
||||
params.walkableHeight = cfg.agent.height;
|
||||
params.walkableRadius = cfg.agent.radius;
|
||||
params.walkableClimb = cfg.agent.max_climb;
|
||||
rcVcopy(params.bmin, pmesh->bmin);
|
||||
rcVcopy(params.bmax, pmesh->bmax);
|
||||
params.cs = m_cfg.cs;
|
||||
params.ch = m_cfg.ch;
|
||||
params.buildBvTree = true;
|
||||
|
||||
unsigned char *navData = 0;
|
||||
int navDataSize = 0;
|
||||
if (!dtCreateNavMeshData(¶ms, &navData, &navDataSize))
|
||||
__ERR__(__LOG_E__ << "Failed to create Detour navmesh.\n", false)
|
||||
|
||||
dtNavMesh *navMesh = dtAllocNavMesh();
|
||||
if (!navMesh)
|
||||
{
|
||||
dtFree(navData);
|
||||
__ERR__(__LOG_E__ << "Failed to build Detour navmesh.\n", false)
|
||||
}
|
||||
|
||||
dtStatus status = navMesh->init(navData, navDataSize, DT_TILE_FREE_DATA);
|
||||
if (dtStatusFailed(status))
|
||||
{
|
||||
dtFree(navData);
|
||||
__ERR__(__LOG_E__ << "Failed to initialize Detour navmesh.\n", false)
|
||||
}
|
||||
/*
|
||||
status = navQuery->init(navMesh, 2048);
|
||||
if (dtStatusFailed(status))
|
||||
__ERR__(__LOG_E__ << "Failed to initialize Detour navmesh query.\n", false)
|
||||
*/
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
191
include/modules/network_enet/enet_network.cpp
Normal file
191
include/modules/network_enet/enet_network.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <cstring>
|
||||
#include "network_enet/enet_network.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "thread/mutex.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using GS::String;
|
||||
using namespace GS::Network;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Enet::GetStatistics(Statistics &stat)
|
||||
{
|
||||
stat.received_data = host->totalReceivedData;
|
||||
stat.sent_data = host->totalSentData;
|
||||
}
|
||||
int Enet::GetPeerPacketLossRatio(void *peer)
|
||||
{
|
||||
ENetPeer *enet_peer = (ENetPeer *)peer;
|
||||
return enet_peer && enet_peer->packetsSent ? (enet_peer->packetsLost * 100) / enet_peer->packetsSent : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Enet::SetPeerTimeout(void *peer, Timeout timeout)
|
||||
{
|
||||
int k = 1;
|
||||
|
||||
switch (timeout)
|
||||
{
|
||||
case TimeoutLong: k = 2; break;
|
||||
case TimeoutVeryLong: k = 4; break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
enet_peer_timeout((ENetPeer *)peer, ENET_PEER_TIMEOUT_LIMIT * k, ENET_PEER_TIMEOUT_MINIMUM * k, ENET_PEER_TIMEOUT_MAXIMUM * k);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Enet::UpdateHost()
|
||||
{
|
||||
if (host)
|
||||
{
|
||||
ENetEvent event;
|
||||
while (enet_host_service(host, &event, 0) > 0)
|
||||
switch (event.type)
|
||||
{
|
||||
case ENET_EVENT_TYPE_CONNECT:
|
||||
OnPeerConnection(event.peer);
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_RECEIVE:
|
||||
OnPacketReceived(event.peer, (void *)event.packet->data, (size_t)event.packet->dataLength);
|
||||
enet_packet_destroy(event.packet);
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_DISCONNECT:
|
||||
OnConnectionClosed(event.peer);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Enet::Close()
|
||||
{
|
||||
if (host)
|
||||
enet_host_destroy(host);
|
||||
host = NULL;
|
||||
}
|
||||
bool Enet::OpenServer(const char *hostname, int port)
|
||||
{
|
||||
Close();
|
||||
|
||||
ENetAddress address;
|
||||
if (hostname)
|
||||
enet_address_set_host(&address, hostname);
|
||||
else
|
||||
address.host = ENET_HOST_ANY;
|
||||
address.port = (enet_uint16)port;
|
||||
|
||||
__LOG__ << "Starting server on " << (hostname ? hostname : "ANY") << ":" << port << "... ";
|
||||
if ((host = enet_host_create(&address, 4, 0, 0, 0)) != NULL)
|
||||
__LOG__ << "OK\n";
|
||||
else
|
||||
__LOG__ << "FAILED\n";
|
||||
/*
|
||||
if (host)
|
||||
enet_host_compress_with_range_coder(host);
|
||||
*/
|
||||
return asbool(host);
|
||||
}
|
||||
bool Enet::OpenClient(const char *hostname, int port)
|
||||
{
|
||||
Close();
|
||||
|
||||
if ((host = enet_host_create(NULL, 1, 0, 0, 0)) == NULL)
|
||||
return false;
|
||||
|
||||
// enet_host_compress_with_range_coder(host);
|
||||
|
||||
ENetAddress address;
|
||||
enet_address_set_host(&address, hostname);
|
||||
address.port = (enet_uint16)port;
|
||||
|
||||
// Connect on one channel to server.
|
||||
__LOG__ << "Opening client connection to " << hostname << ":" << port << "... ";
|
||||
bool r = asbool(enet_host_connect(host, &address, 1, 0));
|
||||
if (r)
|
||||
__LOG__ << "OK.\n";
|
||||
else
|
||||
__LOG__ << "FAILED\n";
|
||||
return r;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Enet::GetHostAddress(String &address)
|
||||
{
|
||||
if (host)
|
||||
{
|
||||
char ip[64];
|
||||
if (enet_address_get_host_ip(&((ENetHost *)host)->address, ip, 63) < 0)
|
||||
return false;
|
||||
address = ip;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool Enet::GetPeerAddress(void *peer, String &address)
|
||||
{
|
||||
if (peer)
|
||||
{
|
||||
char ip[64];
|
||||
if (enet_address_get_host_ip(&((ENetPeer *)peer)->address, ip, 63) < 0)
|
||||
return false;
|
||||
address = ip;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Enet::Send(void *peer, const void *data, size_t size)
|
||||
{
|
||||
// __LOG_V__ << "Send Enet packet of " << size << " bytes.\n";
|
||||
|
||||
ENetPacket *packet = enet_packet_create(data, size, ENET_PACKET_FLAG_RELIABLE);
|
||||
if (!packet || enet_peer_send((ENetPeer *)peer, 0, packet))
|
||||
return false;
|
||||
enet_host_flush(host);
|
||||
return true;
|
||||
}
|
||||
bool Enet::Broadcast(const void *data, size_t size)
|
||||
{
|
||||
ENetPacket *packet = enet_packet_create(data, size, ENET_PACKET_FLAG_RELIABLE);
|
||||
if (!packet)
|
||||
return false;
|
||||
enet_host_broadcast(host, 0, packet);
|
||||
enet_host_flush(host);
|
||||
return true;
|
||||
}
|
||||
void Enet::Disconnect(void *peer)
|
||||
{
|
||||
if (peer)
|
||||
enet_peer_disconnect((ENetPeer *)peer, 0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Enet::Enet()
|
||||
{
|
||||
host = NULL;
|
||||
enet_initialize();
|
||||
}
|
||||
Enet::~Enet()
|
||||
{
|
||||
Close();
|
||||
enet_deinitialize();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
486
include/modules/physic_bullet/bullet_character_controller.cpp
Normal file
486
include/modules/physic_bullet/bullet_character_controller.cpp
Normal file
@ -0,0 +1,486 @@
|
||||
|
||||
|
||||
#include "physic_bullet/bullet_character_controller.h"
|
||||
#include "LinearMath/btIDebugDraw.h"
|
||||
#include "nstring/nstring.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void btCustomCharacterController::debugDraw(btIDebugDraw *idebug)
|
||||
{
|
||||
String output;
|
||||
|
||||
output << "Vertical Velocity: " << mVerticalVelocity << "\n";
|
||||
output << "OnGround: " << (mGroundContact ? "Yes" : "No") << "\n";
|
||||
output << "Ground.y: " << mGroundNormal.y() << "\n";
|
||||
output << "Step high: " << dbg_step_high << "\n";
|
||||
output << "Down sweep: " << dbg_down_sweep_hit << "\n";
|
||||
|
||||
idebug->draw3dText(mCurrentPosition, output.c_str());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
btVector3 btCustomCharacterController::computeReflectionDirection(const btVector3 & direction, const btVector3 & normal)
|
||||
{ return direction - (btScalar(2) * direction.dot(normal)) * normal; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
btCustomCharacterController::btCustomCharacterController(btPairCachingGhostObject * ghostObject, btConvexShape * convexShape, btScalar stepHeight, btCollisionWorld * collisionWorld, int upAxis)
|
||||
{
|
||||
mUpAxis = upAxis;
|
||||
mAddedMargin = 0.02;
|
||||
mWalkDirection.setValue(0, 0, 0);
|
||||
// mUseGhostObjectSweepTest = true;
|
||||
mGhostObject = ghostObject;
|
||||
mStepHeight = stepHeight;
|
||||
mTurnAngle = 0;
|
||||
mConvexShape = mStandingConvexShape = convexShape;
|
||||
mUseWalkDirection = true;
|
||||
mVelocityTimeInterval = 0;
|
||||
mVerticalOffset = 0;
|
||||
mVerticalVelocity = 0;
|
||||
mGravity = 9.8 * 3.0;
|
||||
mFallSpeed = 9.8;
|
||||
mJumpSpeed = 10;
|
||||
// mWasOnGround = false;
|
||||
// mWasJumping = false;
|
||||
setMaxSlope(btRadians(45));
|
||||
mCollisionWorld = collisionWorld;
|
||||
// mCanStand = true;
|
||||
mCurrentPosition.setValue(0, 0, 0);
|
||||
mMass = 20;
|
||||
mGroundContact = false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void btCustomCharacterController::setDuckingConvexShape(btConvexShape * shape)
|
||||
{ mDuckingConvexShape = shape; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void btCustomCharacterController::setRBForceImpulseBasedOnCollision()
|
||||
{
|
||||
if (mWalkDirection.isZero())
|
||||
return;
|
||||
|
||||
for (int i = 0; i < mGhostObject->getOverlappingPairCache()->getNumOverlappingPairs(); ++i)
|
||||
{
|
||||
btBroadphasePair *collisionPair = &mGhostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
|
||||
|
||||
btRigidBody *rb = (btRigidBody*)collisionPair->m_pProxy1->m_clientObject;
|
||||
|
||||
if (mMass > rb->getInvMass())
|
||||
{
|
||||
btScalar resultMass = mMass - rb->getInvMass();
|
||||
btVector3 reflection = computeReflectionDirection(mWalkDirection * resultMass, getNormalizedVector(mWalkDirection));
|
||||
rb->applyCentralImpulse(reflection * -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void btCustomCharacterController::setVelocityForTimeInterval(const btVector3 & velocity, btScalar timeInterval)
|
||||
{
|
||||
mUseWalkDirection = false;
|
||||
mWalkDirection = velocity;
|
||||
mNormalizedDirection = getNormalizedVector(mWalkDirection);
|
||||
mVelocityTimeInterval = timeInterval;
|
||||
}
|
||||
|
||||
void btCustomCharacterController::warp(const btVector3 & origin)
|
||||
{
|
||||
btTransform xform;
|
||||
xform.setIdentity();
|
||||
xform.setOrigin(origin);
|
||||
mGhostObject->setWorldTransform(xform);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool btCustomCharacterController::SweepTest(const btVector3 &src, const btVector3 &dst, btScalar &hitFraction, btVector3 *normal, btVector3 *hit)
|
||||
{
|
||||
btTransform start, end;
|
||||
start.setIdentity(); end.setIdentity();
|
||||
start.setOrigin(src); end.setOrigin(dst);
|
||||
|
||||
ClosestNotMeConvexResultCallback callback(mGhostObject, getUpAxisDirection(), 0);
|
||||
callback.m_collisionFilterGroup = mGhostObject->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback.m_collisionFilterMask = mGhostObject->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
|
||||
mGhostObject->convexSweepTest(mConvexShape, start, end, callback, mCollisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
||||
|
||||
hitFraction = callback.hasHit() ? callback.m_closestHitFraction : btScalar(1);
|
||||
if (normal)
|
||||
*normal = callback.m_hitNormalWorld;
|
||||
if (hit)
|
||||
*hit = callback.m_hitPointWorld;
|
||||
|
||||
return callback.hasHit();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool btCustomCharacterController::recoverFromPenetration(const btVector3 &step_direction)
|
||||
{
|
||||
return false;
|
||||
mCollisionWorld->getDispatcher()->dispatchAllCollisionPairs(mGhostObject->getOverlappingPairCache(), mCollisionWorld->getDispatchInfo(), mCollisionWorld->getDispatcher());
|
||||
|
||||
bool penetration = false;
|
||||
for (int i = 0; i < mGhostObject->getOverlappingPairCache()->getNumOverlappingPairs(); ++i)
|
||||
{
|
||||
btBroadphasePair *collisionPair = &mGhostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
|
||||
|
||||
mManifoldArray.resize(0);
|
||||
if (collisionPair->m_algorithm)
|
||||
collisionPair->m_algorithm->getAllContactManifolds(mManifoldArray);
|
||||
|
||||
for (int j = 0; j < mManifoldArray.size(); ++j)
|
||||
{
|
||||
btPersistentManifold *manifold = mManifoldArray[j];
|
||||
btScalar directionSign = manifold->getBody0() == mGhostObject ? btScalar(1) : btScalar(-1);
|
||||
|
||||
for (int p = 0; p < manifold->getNumContacts(); ++p)
|
||||
{
|
||||
const btManifoldPoint &pt = manifold->getContactPoint(p);
|
||||
|
||||
btScalar dist = pt.getDistance();
|
||||
btVector3 normal = pt.m_normalWorldOnB * directionSign;
|
||||
|
||||
if (dist < 0.0)
|
||||
{
|
||||
penetration = true;
|
||||
|
||||
if (normal.y() > 0.9)
|
||||
normal = btVector3(0, 1, 0); // prevent sliding down slopes
|
||||
|
||||
mCurrentPosition -= normal * dist * btScalar(0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return penetration;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "log/log.h"
|
||||
|
||||
enum
|
||||
{
|
||||
UpSweep,
|
||||
ForwardSweep,
|
||||
DownSweep
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool btCustomCharacterController::SweepAndSlide(btVector3 &from, btVector3 &to, int sweep)
|
||||
{
|
||||
bool hit = false;
|
||||
for (int it = 0; it < 4; ++it)
|
||||
{
|
||||
btScalar hit_fraction;
|
||||
btVector3 hit_normal;
|
||||
if (!SweepTest(from, to, hit_fraction, &hit_normal))
|
||||
return hit;
|
||||
|
||||
switch (sweep)
|
||||
{
|
||||
case ForwardSweep:
|
||||
if (hit_normal.y() < 0.75)
|
||||
{
|
||||
hit_normal.setY(0.0);
|
||||
hit_normal.normalize();
|
||||
}
|
||||
else
|
||||
hit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
from += (to - from) * hit_fraction;
|
||||
to -= hit_normal * (to - from).dot(hit_normal);
|
||||
|
||||
if ((to - from).length2() < btScalar(0.0001))
|
||||
break;
|
||||
}
|
||||
return hit;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void btCustomCharacterController::performStep(btScalar dt)
|
||||
{
|
||||
btScalar hit_fraction;
|
||||
btVector3 hit_normal, hit_point;
|
||||
|
||||
mStepHeight = 0.25;
|
||||
|
||||
// up sweep
|
||||
btVector3 step_height = getUpAxisDirection() * mStepHeight;
|
||||
|
||||
btVector3 wpos = mGhostObject->getWorldTransform().getOrigin();
|
||||
btVector3 tpos = wpos + step_height;
|
||||
|
||||
SweepTest(wpos, tpos, hit_fraction, &hit_normal);
|
||||
tpos = wpos + (tpos - wpos) * hit_fraction;
|
||||
|
||||
// forward sweep
|
||||
bool forward_hit = false;
|
||||
|
||||
if (mWalkDirection.length2() > 0.0)
|
||||
{
|
||||
wpos = tpos;
|
||||
tpos += mWalkDirection;
|
||||
|
||||
forward_hit = SweepAndSlide(wpos, tpos, ForwardSweep);
|
||||
}
|
||||
|
||||
// down sweep
|
||||
btVector3 g = btVector3(0, -9, 0) * dt;
|
||||
|
||||
wpos = tpos;
|
||||
tpos -= step_height;
|
||||
tpos += g;
|
||||
|
||||
bool down_hit = SweepTest(wpos, tpos, hit_fraction, &hit_normal);
|
||||
tpos = wpos + (tpos - wpos) * hit_fraction;
|
||||
|
||||
// landing on a steep slope higher than we starter, revert height change.
|
||||
if (down_hit && (hit_normal.y() < 0.75))
|
||||
{
|
||||
tpos += hit_normal * 0.2;
|
||||
wpos = tpos;
|
||||
tpos = wpos - btVector3(0, 4, 0);
|
||||
|
||||
SweepTest(wpos, tpos, hit_fraction);
|
||||
tpos = wpos + (tpos - wpos) * hit_fraction;
|
||||
}
|
||||
|
||||
|
||||
|
||||
mCurrentPosition = tpos;
|
||||
return;
|
||||
// }
|
||||
/*
|
||||
// perform high sweep to step above small obstacle
|
||||
btVector3 step_height = getUpAxisDirection() * mStepHeight;
|
||||
|
||||
wpos = mGhostObject->getWorldTransform().getOrigin() + step_height;
|
||||
tpos = wpos + mWalkDirection;
|
||||
|
||||
if (!SweepAndSlide(wpos, tpos, HighSweep))
|
||||
return; // high sweep is not cutting it either... drop its result entirely
|
||||
|
||||
// step down from the high sweep
|
||||
wpos = tpos;
|
||||
tpos -= step_height;
|
||||
|
||||
if (!SweepAndSlide(wpos, tpos, DownSweep))
|
||||
{
|
||||
mVerticalVelocity = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// else
|
||||
{
|
||||
mVerticalVelocity = btClamped(mVerticalVelocity - mGravity * dt, -mFallSpeed, mJumpSpeed);
|
||||
|
||||
wpos = tpos;
|
||||
tpos += btVector3(0, mVerticalVelocity, 0) * dt;
|
||||
|
||||
SweepAndSlide(wpos, tpos, GravitySweep);
|
||||
}
|
||||
|
||||
// commit
|
||||
mCurrentPosition = tpos;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void btCustomCharacterController::preStep(btCollisionWorld *collisionWorld)
|
||||
{}
|
||||
void btCustomCharacterController::playerStep(btCollisionWorld * collisionWorld, btScalar dt)
|
||||
{
|
||||
if (!mUseWalkDirection && mVelocityTimeInterval <= 0)
|
||||
return;
|
||||
|
||||
performStep(dt);
|
||||
#if 0
|
||||
mCurrentPosition = mGhostObject->getWorldTransform().getOrigin();
|
||||
|
||||
// Apply gravity.
|
||||
mVerticalVelocity = btClamped(mVerticalVelocity - mGravity * dt, -mFallSpeed, mJumpSpeed);
|
||||
|
||||
// Compute total step velocity.
|
||||
mTouchingContact = false;
|
||||
for (int n = 0; (n < 4) && recoverFromPenetration(mWalkDirection + btVector3(0, -1, 0) * mVerticalVelocity); ++n)
|
||||
mTouchingContact = true;
|
||||
|
||||
// Perform sweep tests.
|
||||
btVector3 stepHeight = getUpAxisDirection() * mStepHeight;
|
||||
btVector3 stepHigh = mCurrentPosition + stepHeight;
|
||||
|
||||
btScalar hitFraction;
|
||||
|
||||
mGroundContact = false;
|
||||
if (SweepTest(stepHigh, stepHigh + mWalkDirection, hitFraction, &mGroundNormal))
|
||||
{
|
||||
btVector3 hit = stepHigh + mWalkDirection * hitFraction;
|
||||
if (mGroundNormal.y() > 0.6) // on ground, take step
|
||||
mCurrentPosition = hit;
|
||||
}
|
||||
else
|
||||
{
|
||||
stepHigh += mWalkDirection; // take the whole walk step
|
||||
|
||||
btVector3 g = stepHeight - mVerticalVelocity * getUpAxisDirection();
|
||||
|
||||
bool down_sweep_hit = SweepTest(stepHigh, stepHigh - g, hitFraction, &mGroundNormal);
|
||||
|
||||
if (!down_sweep_hit)
|
||||
{
|
||||
mCurrentPosition += mVerticalVelocity * getUpAxisDirection(); // free-falling
|
||||
}
|
||||
else
|
||||
{
|
||||
mGroundContact = mGroundNormal.y() > 0.6;
|
||||
|
||||
btVector3 dp = stepHigh - g * hitFraction;
|
||||
|
||||
if (dp.y() > mCurrentPosition.y()) // going up a slope
|
||||
{
|
||||
if (mGroundContact)
|
||||
mCurrentPosition = dp; // ok if on ground
|
||||
}
|
||||
else
|
||||
mCurrentPosition = dp;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//
|
||||
if (mGroundContact)
|
||||
mVerticalVelocity = 0.0;
|
||||
|
||||
//
|
||||
btTransform xform = mGhostObject->getWorldTransform();
|
||||
xform.setOrigin(mCurrentPosition);
|
||||
mGhostObject->setWorldTransform(xform);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void btCustomCharacterController::setFallSpeed(btScalar fallSpeed)
|
||||
{ mFallSpeed = fallSpeed; }
|
||||
void btCustomCharacterController::setJumpSpeed(btScalar jumpSpeed)
|
||||
{ mJumpSpeed = jumpSpeed; }
|
||||
void btCustomCharacterController::setMaxJumpHeight(btScalar maxJumpHeight)
|
||||
{ mMaxJumpHeight = maxJumpHeight; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool btCustomCharacterController::canJump() const
|
||||
{ return onGround(); }
|
||||
void btCustomCharacterController::jump()
|
||||
{
|
||||
if (!canJump())
|
||||
return;
|
||||
|
||||
mVerticalVelocity = mJumpSpeed;
|
||||
// mWasJumping = true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void btCustomCharacterController::duck()
|
||||
{
|
||||
mConvexShape = mDuckingConvexShape;
|
||||
mGhostObject->setCollisionShape(mDuckingConvexShape);
|
||||
|
||||
btTransform xform;
|
||||
xform.setIdentity();
|
||||
xform.setOrigin(mCurrentPosition + btVector3(0, 0.1, 0));
|
||||
mGhostObject->setWorldTransform(xform);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void btCustomCharacterController::stand()
|
||||
{
|
||||
mConvexShape = mStandingConvexShape;
|
||||
mGhostObject->setCollisionShape(mStandingConvexShape);
|
||||
}
|
||||
bool btCustomCharacterController::canStand()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void btCustomCharacterController::setGravity(const btScalar gravity)
|
||||
{ mGravity = gravity; }
|
||||
btScalar btCustomCharacterController::getGravity() const
|
||||
{ return mGravity; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void btCustomCharacterController::setMaxSlope(btScalar slopeRadians)
|
||||
{
|
||||
mMaxSlopeRadians = slopeRadians;
|
||||
mMaxSlopeCosine = btCos(slopeRadians);
|
||||
}
|
||||
btScalar btCustomCharacterController::getMaxSlope() const
|
||||
{ return mMaxSlopeRadians; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool btCustomCharacterController::onGround() const
|
||||
{ return mGroundContact; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void btCustomCharacterController::setWalkDirection(const btVector3 & walkDirection)
|
||||
{
|
||||
mUseWalkDirection = true;
|
||||
mWalkDirection = walkDirection;
|
||||
mNormalizedDirection = getNormalizedVector(mWalkDirection);
|
||||
}
|
||||
void btCustomCharacterController::setWalkDirection(const btScalar x, const btScalar y, const btScalar z)
|
||||
{
|
||||
mUseWalkDirection = true;
|
||||
mWalkDirection.setValue(x, y, z);
|
||||
mNormalizedDirection = getNormalizedVector(mWalkDirection);
|
||||
}
|
||||
btVector3 btCustomCharacterController::getWalkDirection() const
|
||||
{ return mWalkDirection; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
btVector3 btCustomCharacterController::getPosition() const
|
||||
{ return mCurrentPosition; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void btCustomCharacterController::setOrientation(const btQuaternion &orientation)
|
||||
{
|
||||
btTransform xform;
|
||||
xform = mGhostObject->getWorldTransform();
|
||||
xform.setRotation(orientation);
|
||||
mGhostObject->setWorldTransform(xform);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void btCustomCharacterController::updateAction(btCollisionWorld *collisionWorld, btScalar dt)
|
||||
{
|
||||
preStep(collisionWorld);
|
||||
playerStep(collisionWorld, dt);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
176
include/modules/physic_bullet/bullet_constraint.cpp
Normal file
176
include/modules/physic_bullet/bullet_constraint.cpp
Normal file
@ -0,0 +1,176 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "physic_bullet/bullet_constraint.h"
|
||||
#include "physic_bullet/bullet_item.h"
|
||||
#include "scene3d/mitem.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::S3D;
|
||||
|
||||
void BulletConstraint::setLimitHinge(float low, float high, float _softness, float _biasFactor, float _relaxationFactor)
|
||||
{
|
||||
if (!constraint)
|
||||
return;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PhysicConstraintDesc::TypeHinge:
|
||||
((btHingeConstraint*)constraint)->setLimit(low, high, _softness, _biasFactor, _relaxationFactor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletConstraint::SetPivotA(const Matrix4 &pivot)
|
||||
{
|
||||
if (!constraint)
|
||||
return;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PhysicConstraintDesc::TypePoint:
|
||||
{
|
||||
Vector4 p = pivot.GetRow(3);
|
||||
if (item_a.IsValid())
|
||||
p -= ((BulletPhysicItem *)item_a.c_ptr())->GetCenter();
|
||||
|
||||
btVector3 bt_pivot(p.x, p.y, p.z);
|
||||
((btPoint2PointConstraint *)constraint)->setPivotA(bt_pivot);
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
void BulletConstraint::SetPivotB(const Matrix4 &pivot)
|
||||
{
|
||||
if (constraint)
|
||||
switch (type)
|
||||
{
|
||||
case PhysicConstraintDesc::TypePoint:
|
||||
{
|
||||
Vector4 p = pivot.GetRow(3);
|
||||
if (item_b.IsValid())
|
||||
p -= ((BulletPhysicItem *)item_b.c_ptr())->GetCenter();
|
||||
|
||||
btVector3 bt_pivot(p.x, p.y, p.z);
|
||||
((btPoint2PointConstraint *)constraint)->setPivotB(bt_pivot);
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletConstraint::Enable(bool b)
|
||||
{
|
||||
if (constraint)
|
||||
constraint->setEnabled(b);
|
||||
}
|
||||
bool BulletConstraint::SetupConstraint(const PhysicConstraintDesc &desc)
|
||||
{
|
||||
DeleteConstraint();
|
||||
|
||||
// Get constraint items.
|
||||
item_a = desc.item_a.IsValid() ? desc.item_a->physic_item.c_ptr() : NULL;
|
||||
item_b = desc.item_b.IsValid() ? desc.item_b->physic_item.c_ptr() : NULL;
|
||||
|
||||
BulletPhysicItem *bullet_item_a = (BulletPhysicItem *)item_a.c_ptr(),
|
||||
*bullet_item_b = (BulletPhysicItem *)item_b.c_ptr();
|
||||
|
||||
btRigidBody *rigid_body_a = bullet_item_a ? bullet_item_a->rigid_body.c_ptr() : NULL,
|
||||
*rigid_body_b = bullet_item_b ? bullet_item_b->rigid_body.c_ptr() : NULL;
|
||||
|
||||
if (!rigid_body_a && !rigid_body_b)
|
||||
return false;
|
||||
|
||||
// Create constraint.
|
||||
type = desc.type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PhysicConstraintDesc::TypePoint:
|
||||
{
|
||||
Vector4 np_a = desc.pivot_a.GetRow(3), np_b = desc.pivot_b.GetRow(3);
|
||||
|
||||
if (bullet_item_a)
|
||||
np_a -= bullet_item_a->GetCenter();
|
||||
if (bullet_item_b)
|
||||
np_b -= bullet_item_b->GetCenter();
|
||||
|
||||
btVector3 btp_a(np_a.x, np_a.y, np_a.z), btp_b(np_b.x, np_b.y, np_b.z);
|
||||
|
||||
if (rigid_body_a && rigid_body_b)
|
||||
constraint = new btPoint2PointConstraint(*rigid_body_a, *rigid_body_b, btp_a, btp_b);
|
||||
if (rigid_body_a && !rigid_body_b)
|
||||
constraint = new btPoint2PointConstraint(*rigid_body_a, btp_a);
|
||||
|
||||
// constraint->setParam(BT_CONSTRAINT_ERP, 0.8);
|
||||
// constraint->setParam(BT_CONSTRAINT_CFM, 0);
|
||||
}
|
||||
break;
|
||||
case PhysicConstraintDesc::TypeHinge:
|
||||
{
|
||||
Vector4 np_a = desc.pivot_a.GetRow(3), np_b = desc.pivot_b.GetRow(3);
|
||||
|
||||
if (bullet_item_a)
|
||||
np_a -= bullet_item_a->GetCenter();
|
||||
if (bullet_item_b)
|
||||
np_b -= bullet_item_b->GetCenter();
|
||||
|
||||
btVector3 btp_a(np_a.x, np_a.y, np_a.z), btp_b(np_b.x, np_b.y, np_b.z);
|
||||
|
||||
if (rigid_body_a && rigid_body_b)
|
||||
constraint = new btHingeConstraint(*rigid_body_a, *rigid_body_b, btp_a, btp_b, btVector3(0,0,1), btVector3(0,0,1));
|
||||
if (rigid_body_a && !rigid_body_b)
|
||||
constraint = new btHingeConstraint(*rigid_body_a, btp_a, btVector3(0,1,0));
|
||||
// ((btHingeConstraint*)constraint)->setLimit(0, 0);
|
||||
// constraint->setParam(BT_CONSTRAINT_STOP_CFM, 0);
|
||||
// constraint->setParam(BT_CONSTRAINT_CFM, 0);
|
||||
// constraint->setParam(BT_CONSTRAINT_STOP_ERP, 0.8);
|
||||
// constraint->setParam(BT_CONSTRAINT_ERP, 0.8);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (constraint)
|
||||
world->addConstraint(constraint);
|
||||
|
||||
return true;
|
||||
}
|
||||
void BulletConstraint::DeleteConstraint()
|
||||
{
|
||||
if (constraint)
|
||||
{
|
||||
world->removeConstraint(constraint);
|
||||
_safe_delete(constraint);
|
||||
}
|
||||
|
||||
item_a = NULL;
|
||||
item_b = NULL;
|
||||
|
||||
type = PhysicConstraintDesc::TypeNone;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
BulletConstraint::BulletConstraint(btDiscreteDynamicsWorld *_world)
|
||||
{
|
||||
type = PhysicConstraintDesc::TypeNone;
|
||||
|
||||
world = _world;
|
||||
constraint = NULL;
|
||||
}
|
||||
BulletConstraint::~BulletConstraint()
|
||||
{
|
||||
DeleteConstraint();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
83
include/modules/physic_bullet/bullet_debug.cpp
Normal file
83
include/modules/physic_bullet/bullet_debug.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "physic_bullet/bullet_debug.h"
|
||||
#include "core/renderer.h"
|
||||
#include "core/renderer_toolbox.h"
|
||||
#include "core/camera.h"
|
||||
#include "gpu/gpu_renderer.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletDebugDraw::Flush()
|
||||
{
|
||||
renderer.DrawLine(line_count, vtx_cache, col_cache, xray_first_pass ? GS::Core::Material::Blend_Alpha : GS::Core::Material::Blend_None, GS::Core::Material::Render_NoZWrite);
|
||||
line_count = 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
float BulletDebugDraw::GetXRayAlpha() const
|
||||
{ return xray_first_pass ? 0.2f : 1.f; }
|
||||
void BulletDebugDraw::SetXRayFirstPass(bool pass)
|
||||
{
|
||||
// FIXME: WTF!?
|
||||
((GS::GPU::Renderer &)renderer).SetDepthFunc(pass ? GS::GPU::Renderer::DepthGreater : GS::GPU::Renderer::DepthLessEqual);
|
||||
xray_first_pass = pass;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletDebugDraw::drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)
|
||||
{
|
||||
if (line_count == 2048)
|
||||
Flush();
|
||||
|
||||
vtx_cache[(line_count << 1) + 0].Set(from.x(), from.y(), from.z());
|
||||
vtx_cache[(line_count << 1) + 1].Set(to.x(), to.y(), to.z());
|
||||
col_cache[(line_count << 1) + 0].Set(color.x(), color.y(), color.z(), GetXRayAlpha());
|
||||
col_cache[(line_count << 1) + 1].Set(color.x(), color.y(), color.z(), GetXRayAlpha());
|
||||
|
||||
++line_count;
|
||||
}
|
||||
void BulletDebugDraw::drawContactPoint(const btVector3 &PointOnB, const btVector3 &/*normalOnB*/, btScalar /*distance*/, int /*lifeTime*/, const btVector3 &color)
|
||||
{
|
||||
drawLine(PointOnB - btVector3(0.25, 0, 0), PointOnB + btVector3(0.25, 0, 0), color);
|
||||
drawLine(PointOnB - btVector3(0, 0.25, 0), PointOnB + btVector3(0, 0.25, 0), color);
|
||||
drawLine(PointOnB - btVector3(0, 0, 0.25), PointOnB + btVector3(0, 0, 0.25), color);
|
||||
}
|
||||
void BulletDebugDraw::reportErrorWarning(const char *)
|
||||
{}
|
||||
void BulletDebugDraw::draw3dText(const btVector3 &p, const char *text)
|
||||
{
|
||||
if (camera && raster_font)
|
||||
{
|
||||
Matrix4 m = camera->GetMatrix();
|
||||
m.SetRow(3, Vector4(p.x(), p.y(), p.z()));
|
||||
renderer.SetWorldMatrix(m);
|
||||
|
||||
float x = 0, y = 0;
|
||||
Renderer::WriterConfig config(true, false);
|
||||
renderer.Write(*raster_font, text, x, y, config, 2.f);
|
||||
|
||||
renderer.SetWorldMatrix(Matrix4::IdentityMatrix(), &Matrix4::IdentityMatrix());
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
BulletDebugDraw::BulletDebugDraw(Renderer &r) : renderer(r)
|
||||
{
|
||||
vtx_cache.Allocate(2048 * 2);
|
||||
col_cache.Allocate(2048 * 2);
|
||||
line_count = 0;
|
||||
|
||||
camera = NULL;
|
||||
raster_font = NULL;
|
||||
|
||||
xray_first_pass = true;
|
||||
}
|
||||
821
include/modules/physic_bullet/bullet_item.cpp
Normal file
821
include/modules/physic_bullet/bullet_item.cpp
Normal file
@ -0,0 +1,821 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "physic_bullet/bullet_item.h"
|
||||
#include "physic_bullet/bullet_world.h"
|
||||
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
|
||||
#include "physic_bullet/bullet_character_controller.h"
|
||||
#include "physic/physic_item_desc.h"
|
||||
#include "core/item.h"
|
||||
#include "core/terrain.h"
|
||||
#include "scene3d/mitem.h"
|
||||
#include "math/matrix4.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static Vector4 btTonVector(const btVector3 &v)
|
||||
{ return Vector4(v.x(), v.y(), v.z()); }
|
||||
static btVector3 nTobtVector(const Vector4 &v)
|
||||
{ return btVector3(v.x, v.y, v.z); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletMotionState::setWorldTransform(const btTransform &comt)
|
||||
{
|
||||
btTransform wt = comt;
|
||||
const Vector4 &com = item->GetCenter();
|
||||
wt.setOrigin(wt.getOrigin() - wt.getBasis() * btVector3(com.x, com.y, com.z));
|
||||
item->TransformToMatrix4(wt, bullet_matrix);
|
||||
bullet_matrix = bullet_matrix * Matrix4::ScaleMatrix(item->GetScale());
|
||||
}
|
||||
void BulletMotionState::getWorldTransform(btTransform &wt) const
|
||||
{
|
||||
item->TransformFromMatrix4(engine_matrix, wt);
|
||||
const Vector4 &com = item->GetCenter();
|
||||
wt.setOrigin(wt.getOrigin() + wt.getBasis() * btVector3(com.x, com.y, com.z));
|
||||
}
|
||||
BulletMotionState::BulletMotionState(BulletPhysicItem *_item) : item(_item)
|
||||
{
|
||||
MItem *mitem = (MItem *)_item->GetUserPointer();
|
||||
bullet_matrix = mitem->GetBaseItem()->GetMatrix();
|
||||
engine_matrix = bullet_matrix;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
uint BulletPhysicItem::GetSelfMask() const
|
||||
{
|
||||
btBroadphaseProxy *handle = NULL;
|
||||
if (rigid_body)
|
||||
handle = rigid_body->getBroadphaseHandle();
|
||||
if (ghost_object)
|
||||
handle = ghost_object->getBroadphaseHandle();
|
||||
|
||||
return handle ? handle->m_collisionFilterGroup : 0;
|
||||
}
|
||||
void BulletPhysicItem::SetSelfMask(uint m)
|
||||
{
|
||||
self_mask = m;
|
||||
|
||||
btBroadphaseProxy *handle = NULL;
|
||||
if (rigid_body)
|
||||
handle = rigid_body->getBroadphaseHandle();
|
||||
if (ghost_object)
|
||||
handle = ghost_object->getBroadphaseHandle();
|
||||
|
||||
if (handle)
|
||||
{
|
||||
handle->m_collisionFilterGroup = (short)m;
|
||||
|
||||
// Refresh pair cache.
|
||||
btworld->getBroadphase()->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(handle, btworld->getDispatcher());
|
||||
}
|
||||
}
|
||||
uint BulletPhysicItem::GetCollisionMask() const
|
||||
{
|
||||
btBroadphaseProxy *handle = NULL;
|
||||
if (rigid_body)
|
||||
handle = rigid_body->getBroadphaseHandle();
|
||||
if (ghost_object)
|
||||
handle = ghost_object->getBroadphaseHandle();
|
||||
|
||||
return handle ? handle->m_collisionFilterMask : 0;
|
||||
}
|
||||
void BulletPhysicItem::SetCollisionMask(uint m)
|
||||
{
|
||||
collision_mask = m;
|
||||
|
||||
btBroadphaseProxy *handle = NULL;
|
||||
if (rigid_body)
|
||||
handle = rigid_body->getBroadphaseHandle();
|
||||
if (ghost_object)
|
||||
handle = ghost_object->getBroadphaseHandle();
|
||||
|
||||
if (handle)
|
||||
{
|
||||
handle->m_collisionFilterMask = (short)m;
|
||||
|
||||
// Refresh pair cache.
|
||||
btworld->getBroadphase()->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(handle, btworld->getDispatcher());
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletPhysicItem::SetLinearDamping(float k)
|
||||
{
|
||||
if (rigid_body)
|
||||
rigid_body->setDamping(1.f - k, rigid_body->getAngularDamping());
|
||||
}
|
||||
float BulletPhysicItem::GetLinearDamping() const
|
||||
{
|
||||
return rigid_body ? 1.f - rigid_body->getLinearDamping() : 0;
|
||||
}
|
||||
void BulletPhysicItem::SetAngularDamping(float k)
|
||||
{
|
||||
if (rigid_body)
|
||||
rigid_body->setDamping(rigid_body->getLinearDamping(), 1.f - k);
|
||||
}
|
||||
float BulletPhysicItem::GetAngularDamping() const
|
||||
{
|
||||
return rigid_body ? 1.f - rigid_body->getAngularDamping() : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletPhysicItem::SetLinearFactor(const Vector4 &k)
|
||||
{
|
||||
if (rigid_body)
|
||||
rigid_body->setLinearFactor(btVector3(k.x, k.y, k.z));
|
||||
}
|
||||
void BulletPhysicItem::SetAngularFactor(const Vector4 &k)
|
||||
{
|
||||
if (rigid_body)
|
||||
rigid_body->setAngularFactor(btVector3(k.x, k.y, k.z));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletPhysicItem::TransformFromMatrix4(const Matrix4 &m, btTransform &transform)
|
||||
{
|
||||
btScalar scalar[15];
|
||||
scalar[0] = m.m[0][0]; scalar[1] = m.m[1][0]; scalar[2] = m.m[2][0]; scalar[3] = 1;
|
||||
scalar[4] = m.m[0][1]; scalar[5] = m.m[1][1]; scalar[6] = m.m[2][1]; scalar[7] = 1;
|
||||
scalar[8] = m.m[0][2]; scalar[9] = m.m[1][2]; scalar[10] = m.m[2][2]; scalar[11] = 1;
|
||||
scalar[12] = m.m[0][3]; scalar[13] = m.m[1][3]; scalar[14] = m.m[2][3];
|
||||
transform.setFromOpenGLMatrix(scalar);
|
||||
}
|
||||
void BulletPhysicItem::TransformToMatrix4(const btTransform &transform, Matrix4 &m)
|
||||
{
|
||||
btScalar scalar[16];
|
||||
transform.getOpenGLMatrix(scalar);
|
||||
m.m[0][0] = scalar[0]; m.m[1][0] = scalar[1]; m.m[2][0] = scalar[2]; m.m[3][0] = 0;
|
||||
m.m[0][1] = scalar[4]; m.m[1][1] = scalar[5]; m.m[2][1] = scalar[6]; m.m[3][1] = 0;
|
||||
m.m[0][2] = scalar[8]; m.m[1][2] = scalar[9]; m.m[2][2] = scalar[10]; m.m[3][2] = 0;
|
||||
m.m[0][3] = scalar[12]; m.m[1][3] = scalar[13]; m.m[2][3] = scalar[14]; m.m[3][3] = scalar[15];
|
||||
}
|
||||
void BulletPhysicItem::GetGraphicMatrix(Matrix4 &m)
|
||||
{
|
||||
if (ghost_object)
|
||||
{
|
||||
btTransform wt = ghost_object->getWorldTransform();
|
||||
wt.setOrigin(wt.getOrigin() - wt.getBasis() * btVector3(center.x, center.y, center.z));
|
||||
TransformToMatrix4(wt, m);
|
||||
}
|
||||
else
|
||||
if (motion_state)
|
||||
m = motion_state->GetGraphicMatrix();
|
||||
}
|
||||
void BulletPhysicItem::SetEngineMatrix(const Matrix4 &m)
|
||||
{
|
||||
if (motion_state)
|
||||
motion_state->SetEngineMatrix(m);
|
||||
}
|
||||
void BulletPhysicItem::GetMatrix(Matrix4 &m)
|
||||
{
|
||||
if (ghost_object)
|
||||
TransformToMatrix4(ghost_object->getWorldTransform(), m);
|
||||
else
|
||||
if (rigid_body)
|
||||
TransformToMatrix4(rigid_body->getWorldTransform(), m);
|
||||
}
|
||||
void BulletPhysicItem::SetMatrix(const Matrix4 &m)
|
||||
{
|
||||
Vector4 p;
|
||||
Matrix3 m3;
|
||||
m.Decompose(&p, 0, &m3);
|
||||
Matrix4 m4(Matrix4::FromMatrix3(m3));
|
||||
m4.SetRow(3, p);
|
||||
|
||||
btTransform wt;
|
||||
TransformFromMatrix4(m4, wt);
|
||||
wt.setOrigin(wt.getOrigin() + wt.getBasis() * btVector3(center.x, center.y, center.z));
|
||||
|
||||
if (ghost_object)
|
||||
ghost_object->setWorldTransform(wt);
|
||||
else
|
||||
if (rigid_body)
|
||||
rigid_body->setWorldTransform(wt);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletPhysicItem::SetSleeping(bool sleep)
|
||||
{
|
||||
if (!rigid_body)
|
||||
return;
|
||||
|
||||
if (sleep)
|
||||
rigid_body->setActivationState(WANTS_DEACTIVATION);
|
||||
else rigid_body->activate();
|
||||
}
|
||||
bool BulletPhysicItem::IsSleeping() const
|
||||
{ return rigid_body ? rigid_body->wantsSleeping() : false; }
|
||||
void BulletPhysicItem::SetActive(bool active)
|
||||
{
|
||||
if (!rigid_body)
|
||||
return;
|
||||
|
||||
if (active)
|
||||
{
|
||||
/*
|
||||
Note the activation state MUST be changed from
|
||||
DISABLE_SIMULATION or activate() will silently fail.
|
||||
*/
|
||||
rigid_body->getBroadphaseHandle()->m_collisionFilterGroup = self_mask;
|
||||
rigid_body->getBroadphaseHandle()->m_collisionFilterMask = collision_mask;
|
||||
rigid_body->forceActivationState(ACTIVE_TAG);
|
||||
rigid_body->activate();
|
||||
}
|
||||
else
|
||||
{
|
||||
rigid_body->setActivationState(DISABLE_SIMULATION);
|
||||
rigid_body->getBroadphaseHandle()->m_collisionFilterGroup = 0;
|
||||
rigid_body->getBroadphaseHandle()->m_collisionFilterMask = 0;
|
||||
}
|
||||
}
|
||||
bool BulletPhysicItem::GetActive() const
|
||||
{ return rigid_body ? rigid_body->isActive() : false; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletPhysicItem::VehicleSetForce(float F, uint i)
|
||||
{
|
||||
if (vehicle && (i < (uint)vehicle->getNumWheels()))
|
||||
vehicle->applyEngineForce(F, i);
|
||||
}
|
||||
void BulletPhysicItem::VehicleSetBrake(float F, uint i)
|
||||
{
|
||||
if (vehicle && (i < (uint)vehicle->getNumWheels()))
|
||||
vehicle->setBrake(F, i);
|
||||
}
|
||||
void BulletPhysicItem::VehicleSetSteering(float v, uint i)
|
||||
{
|
||||
if (vehicle && (i < (uint)vehicle->getNumWheels()))
|
||||
vehicle->setSteeringValue(v, i);
|
||||
}
|
||||
void BulletPhysicItem::VehicleSetFriction(float f, uint i)
|
||||
{
|
||||
if (vehicle && (i < (uint)vehicle->getNumWheels()))
|
||||
vehicle->getWheelInfo(i).m_frictionSlip = f;
|
||||
}
|
||||
Matrix4 BulletPhysicItem::VehicleGetWheelMatrix(uint i)
|
||||
{
|
||||
Matrix4 m(Matrix4::IdentityMatrix());
|
||||
if (vehicle && (i < (uint)vehicle->getNumWheels()))
|
||||
{
|
||||
vehicle->updateWheelTransform(i, true);
|
||||
TransformToMatrix4(vehicle->getWheelInfo(i).m_worldTransform, m);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletPhysicItem::CharacterSetRotationMatrix(const Matrix3 &m)
|
||||
{
|
||||
if (ghost_object)
|
||||
{
|
||||
btMatrix3x3 basis
|
||||
(
|
||||
m.m[0][0], m.m[0][1], m.m[0][2],
|
||||
m.m[1][0], m.m[1][1], m.m[1][2],
|
||||
m.m[2][0], m.m[2][1], m.m[2][2]
|
||||
);
|
||||
ghost_object->getWorldTransform().setBasis(basis);
|
||||
}
|
||||
}
|
||||
void BulletPhysicItem::CharacterSetVelocity(const Vector4 &v)
|
||||
{
|
||||
if (character_controller)
|
||||
character_controller->setWalkDirection(nTobtVector(v));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletPhysicItem::SetScale(const Vector4 &_scale)
|
||||
{
|
||||
scale = _scale;
|
||||
if (compound)
|
||||
compound->setLocalScaling(nTobtVector(scale));
|
||||
}
|
||||
Vector4 BulletPhysicItem::GetScale() const
|
||||
{ return scale; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletPhysicItem::ResetBody()
|
||||
{
|
||||
if (rigid_body)
|
||||
{
|
||||
rigid_body->setLinearVelocity(btVector3(0, 0, 0));
|
||||
rigid_body->setAngularVelocity(btVector3(0, 0, 0));
|
||||
rigid_body->clearForces();
|
||||
}
|
||||
}
|
||||
void BulletPhysicItem::ForceUpdateMassShapePhysic(const PhysicItemDesc &desc, PhysicWorld *world)
|
||||
{
|
||||
float total_mass = 0;
|
||||
if (!desc.shape_list.GetCount())
|
||||
return;
|
||||
|
||||
Array <btScalar> mass_array;
|
||||
mass_array.Allocate(desc.shape_list.GetCount());
|
||||
center.Set(0, 0, 0);
|
||||
btScalar *pmass_array = mass_array.c_ptr();
|
||||
|
||||
ListForeachPtr(PhysicShape *, shape, desc.shape_list)
|
||||
{
|
||||
Vector4 shape_center = shape->position;
|
||||
center += shape_center * shape->mass;
|
||||
total_mass += shape->mass;
|
||||
*pmass_array++ = shape->mass;
|
||||
}
|
||||
center /= total_mass;
|
||||
btTransform principal;
|
||||
btVector3 body_inertia(0, 0, 0);
|
||||
compound->calculatePrincipalAxisTransform(mass_array, principal, body_inertia);
|
||||
|
||||
rigid_body->setMassProps(total_mass, body_inertia);
|
||||
rigid_body->updateInertiaTensor();
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
float BulletPhysicItem::SetupCollisionShapes(const PhysicItemDesc &desc, Array <btScalar> &mass_array, PhysicWorld *world)
|
||||
{
|
||||
float total_mass = 0;
|
||||
if (!desc.shape_list.GetCount())
|
||||
return total_mass;
|
||||
|
||||
mass_array.Allocate(desc.shape_list.GetCount());
|
||||
btScalar *pmass_array = mass_array.c_ptr();
|
||||
|
||||
// WTF man... can't Bullet handle COM offset by itself?
|
||||
shapes.Allocate(desc.shape_list.GetCount());
|
||||
|
||||
center.Set(0, 0, 0);
|
||||
|
||||
uint n = 0;
|
||||
ListForeachPtr(PhysicShape *, shape, desc.shape_list)
|
||||
{
|
||||
btCollisionShape *btshape = NULL;
|
||||
Vector4 shape_center = shape->position;
|
||||
|
||||
switch (shape->GetType())
|
||||
{
|
||||
case PhysicShape::TypeNone:
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeHeightmap:
|
||||
if (float *ph = shape->GetHeightmap())
|
||||
{
|
||||
float min, max;
|
||||
min = max = ph[0];
|
||||
for (int v = 0; v < shape->GetHeight(); ++v)
|
||||
for (int u = 0; u < shape->GetWidth(); ++u)
|
||||
{
|
||||
if (ph[0] > max)
|
||||
max = ph[0];
|
||||
if (ph[0] < min)
|
||||
min = ph[0];
|
||||
ph++;
|
||||
}
|
||||
|
||||
btshape = new btHeightfieldTerrainShape(shape->GetWidth(), shape->GetHeight(), (void *)shape->GetHeightmap(), 1.f, min, max, 1, PHY_FLOAT, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeSphere:
|
||||
btshape = new btSphereShape(shape->dimensions.x);
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeBox:
|
||||
{
|
||||
const Vector4 &d = shape->dimensions;
|
||||
btshape = new btBoxShape(btVector3(d.x * 0.5f, d.y * 0.5f, d.z * 0.5f));
|
||||
}
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeCapsule:
|
||||
{
|
||||
const Vector4 &d = shape->dimensions;
|
||||
btshape = new btCapsuleShapeZ(d.x * 0.5f, d.z);
|
||||
}
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeCylinder:
|
||||
{
|
||||
const Vector4 &d = shape->dimensions;
|
||||
btshape = new btCylinderShapeZ(btVector3(d.x * 0.5f, d.y * 0.5f, d.z * 0.5f));
|
||||
}
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeCone:
|
||||
{
|
||||
const Vector4 &d = shape->dimensions;
|
||||
btshape = new btConeShapeZ(d.x * 0.5f, d.z * 0.5f);
|
||||
}
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeConvex:
|
||||
if (BulletConvex *convex = ((BulletWorld *)world)->LoadConvex(shape->path))
|
||||
{
|
||||
shapes[n].convex = convex;
|
||||
|
||||
shape_center = convex->center * shape->GetMatrix();
|
||||
btshape = convex->convex;
|
||||
}
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeMesh:
|
||||
if (desc.physic_mode == PhysicItemDesc::Mode_Static)
|
||||
{
|
||||
/*
|
||||
[EJ] 06/03/13 - Bullet SILENTLY rescales the cached mesh
|
||||
vertices to comply with the item scale. In order to support
|
||||
multiple scales on the same mesh the path is suffixed with
|
||||
the item scale.
|
||||
*/
|
||||
String suffix = String::Format("%.02f_%.02f_%.02f", scale.x, scale.y, scale.z);
|
||||
|
||||
if (BulletMesh *mesh = ((BulletWorld *)world)->LoadMesh(shape->path, suffix))
|
||||
{
|
||||
shapes[n].mesh = mesh;
|
||||
|
||||
shape_center = mesh->center * shape->GetMatrix();
|
||||
btshape = mesh->mesh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
shapes[n].shape = btshape;
|
||||
|
||||
center += shape_center * shape->mass;
|
||||
total_mass += shape->mass;
|
||||
*pmass_array++ = shape->mass;
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
center /= total_mass;
|
||||
if (desc.physic_mode == PhysicItemDesc::Mode_Vehicle)
|
||||
center.Set(0, 0, 0);
|
||||
|
||||
n = 0;
|
||||
ListForeachPtr(PhysicShape *, shape, desc.shape_list)
|
||||
{
|
||||
if (btCollisionShape *btshape = shapes[n].shape)
|
||||
{
|
||||
Vector4 shape_offset(0, 0, 0);
|
||||
|
||||
if (shape->GetType() == PhysicShape::TypeHeightmap)
|
||||
{
|
||||
float *ph = shape->GetHeightmap();
|
||||
|
||||
float min, max;
|
||||
min = max = ph[0];
|
||||
|
||||
for (int v = 0; v < shape->GetHeight(); ++v)
|
||||
for (int u = 0; u < shape->GetWidth(); ++u)
|
||||
{
|
||||
if (ph[0] > max) max = ph[0];
|
||||
if (ph[0] < min) min = ph[0];
|
||||
ph++;
|
||||
}
|
||||
|
||||
btshape->setLocalScaling(btVector3(1, 1, 1));
|
||||
|
||||
// Damn... what a mess.
|
||||
float hy = (max - min) * -0.5f;
|
||||
shape_offset.Set(0, min - hy, 0);
|
||||
}
|
||||
|
||||
Matrix4 m = Matrix4::TransformationMatrix(shape->position + shape_offset - center, shape->rotation, shape->scale);
|
||||
btTransform transform;
|
||||
TransformFromMatrix4(m, transform);
|
||||
|
||||
compound->addChildShape(transform, btshape);
|
||||
}
|
||||
++n;
|
||||
}
|
||||
return total_mass;
|
||||
}
|
||||
bool BulletPhysicItem::SetupCharacterController(const PhysicItemDesc &desc)
|
||||
{
|
||||
ghost_object = new btPairCachingGhostObject();
|
||||
ghost_object->setUserPointer((PhysicItem *)this);
|
||||
|
||||
#if 0
|
||||
convex_shape = new btCylinderShape(btVector3(desc.character.radius, desc.character.height * 0.5f, desc.character.radius));
|
||||
center.Set(0, desc.character.height * 0.5f, 0);
|
||||
#else
|
||||
float height = Types::Max(desc.character.height - desc.character.radius * 2.f, 0.f);
|
||||
convex_shape = new btCapsuleShape(desc.character.radius, height); // Height is the distance between the center of the two spheres whose convex hull is a capsule.
|
||||
center.Set(0, (height + desc.character.radius * 2.f) * 0.5f, 0);
|
||||
#endif
|
||||
|
||||
ghost_object->setCollisionShape(convex_shape);
|
||||
ghost_object->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
|
||||
|
||||
#if 1
|
||||
character_controller = new btKinematicCharacterController(ghost_object, convex_shape, desc.character.max_step);
|
||||
#else
|
||||
btCustomCharacterController *cc = new btCustomCharacterController(ghost_object, convex_shape, desc.character.max_step, btworld->getCollisionWorld());
|
||||
character_controller = cc;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
bool BulletPhysicItem::SetupKinematicDynamicBody(const PhysicItemDesc &desc, PhysicWorld *world)
|
||||
{
|
||||
// Setup collision shapes.
|
||||
Array <btScalar> mass_array;
|
||||
|
||||
compound = new btCompoundShape;
|
||||
float total_mass = SetupCollisionShapes(desc, mass_array, world);
|
||||
|
||||
if (!compound->getNumChildShapes())
|
||||
return true;
|
||||
|
||||
// Initialize physic mode.
|
||||
compound->setLocalScaling(nTobtVector(scale));
|
||||
btVector3 body_inertia(0, 0, 0);
|
||||
|
||||
switch (desc.physic_mode)
|
||||
{
|
||||
case PhysicItemDesc::Mode_None:
|
||||
break;
|
||||
|
||||
case PhysicItemDesc::Mode_Dynamic:
|
||||
case PhysicItemDesc::Mode_Vehicle:
|
||||
if (compound->getNumChildShapes())
|
||||
{
|
||||
btTransform principal;
|
||||
compound->calculatePrincipalAxisTransform(mass_array, principal, body_inertia);
|
||||
}
|
||||
else
|
||||
{
|
||||
total_mass = 1;
|
||||
body_inertia.setValue(1, 1, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case PhysicItemDesc::Mode_Static:
|
||||
case PhysicItemDesc::Mode_Kinematic:
|
||||
total_mass = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Allocate motion state.
|
||||
motion_state = new BulletMotionState(this);
|
||||
|
||||
// Create rigid body.
|
||||
rigid_body = new btRigidBody(btRigidBody::btRigidBodyConstructionInfo(total_mass, motion_state, compound, body_inertia));
|
||||
rigid_body->setUserPointer((PhysicItem *)this);
|
||||
|
||||
// Vehicle specialization.
|
||||
if (desc.physic_mode == PhysicItemDesc::Mode_Vehicle)
|
||||
{
|
||||
rigid_body->setActivationState(DISABLE_DEACTIVATION);
|
||||
|
||||
vehicle_raycaster = new btDefaultVehicleRaycaster(btworld);
|
||||
vehicle = new btRaycastVehicle(btRaycastVehicle::btVehicleTuning(), rigid_body, vehicle_raycaster);
|
||||
vehicle->setCoordinateSystem(0, 1, 2);
|
||||
|
||||
// Add wheels.
|
||||
ListForeachPtr(PhysicWheel *, wheel, desc.vehicle.wheel_list)
|
||||
{
|
||||
btRaycastVehicle::btVehicleTuning tuning;
|
||||
|
||||
tuning.m_suspensionStiffness = wheel->stiffness;
|
||||
tuning.m_suspensionDamping = wheel->damping;
|
||||
tuning.m_suspensionCompression = wheel->damping;
|
||||
tuning.m_frictionSlip = wheel->friction;
|
||||
tuning.m_maxSuspensionTravelCm = wheel->max_compression * 10.f; // m to cm.
|
||||
|
||||
Vector4 o = wheel->ref_matrix.GetRow(3),
|
||||
u = wheel->ref_matrix.GetRow(1).Reversed(),
|
||||
l = wheel->ref_matrix.GetRow(0).Reversed();
|
||||
|
||||
vehicle->addWheel(btVector3(o.x, o.y, o.z), btVector3(u.x, u.y, u.z), btVector3(l.x, l.y, l.z), wheel->rest_length, wheel->radius > 0.01f ? wheel->radius : 0.01f, tuning, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Set defaults.
|
||||
SetLinearFactor(desc.linear_factor);
|
||||
SetAngularFactor(desc.angular_factor);
|
||||
SetLinearDamping(desc.linear_damping);
|
||||
SetAngularDamping(desc.angular_damping);
|
||||
|
||||
if (desc.shape_list.GetCount())
|
||||
{
|
||||
PhysicShape *shape = desc.shape_list.GetRoot()->Object();
|
||||
rigid_body->setFriction(shape->static_friction);
|
||||
rigid_body->setRestitution(shape->restitution);
|
||||
}
|
||||
|
||||
if (desc.physic_mode == PhysicItemDesc::Mode_Kinematic)
|
||||
{
|
||||
rigid_body->setCollisionFlags(rigid_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||
rigid_body->setActivationState(DISABLE_DEACTIVATION);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool BulletPhysicItem::SetupBody(const PhysicItemDesc &desc, PhysicWorld *world)
|
||||
{
|
||||
// EJ 11/10
|
||||
//
|
||||
// - Bullet constraint holds strong/unmanaged reference to Bullet rigid bodies.
|
||||
// - A Bullet rigid body is not meant to be radically modified once created.
|
||||
|
||||
// BulletWorld *world = (PhysicWorld *)world;
|
||||
|
||||
if (rigid_body || ghost_object)
|
||||
return true;
|
||||
|
||||
DeleteBody();
|
||||
|
||||
switch (desc.physic_mode)
|
||||
{
|
||||
case PhysicItemDesc::Mode_None:
|
||||
return true;
|
||||
|
||||
case PhysicItemDesc::Mode_Character:
|
||||
if (!SetupCharacterController(desc))
|
||||
return false;
|
||||
|
||||
btworld->addCollisionObject(ghost_object, btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
|
||||
btworld->addAction(character_controller);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!SetupKinematicDynamicBody(desc, world))
|
||||
return false;
|
||||
|
||||
if (rigid_body)
|
||||
{
|
||||
btworld->addRigidBody(rigid_body);
|
||||
const Vector4 &g(world->GetGravity());
|
||||
rigid_body->setGravity(btVector3(g.x, g.y, g.z));
|
||||
}
|
||||
if (vehicle)
|
||||
btworld->addVehicle(vehicle);
|
||||
break;
|
||||
}
|
||||
|
||||
SetCollisionMask(desc.collision_mask);
|
||||
SetSelfMask(desc.self_mask);
|
||||
return true;
|
||||
}
|
||||
void BulletPhysicItem::DeleteBody()
|
||||
{
|
||||
// Destroy all shapes.
|
||||
if (compound)
|
||||
while (compound->getNumChildShapes())
|
||||
compound->removeChildShapeByIndex(0);
|
||||
|
||||
// The collision shape for mesh/convex are cached and should not be deleted here!
|
||||
for (uint n = 0; n < shapes.GetCount(); ++n)
|
||||
if (shapes[n].convex.IsValid() || shapes[n].mesh.IsValid())
|
||||
shapes[n].shape.Detach();
|
||||
|
||||
shapes.Free();
|
||||
|
||||
// Destroy rigid body.
|
||||
if (rigid_body)
|
||||
btworld->removeRigidBody(rigid_body);
|
||||
rigid_body = NULL;
|
||||
|
||||
if (vehicle)
|
||||
btworld->removeVehicle(vehicle);
|
||||
vehicle = NULL;
|
||||
vehicle_raycaster = NULL;
|
||||
|
||||
if (ghost_object)
|
||||
btworld->removeCollisionObject(ghost_object);
|
||||
ghost_object = NULL;
|
||||
|
||||
if (character_controller)
|
||||
btworld->removeAction(character_controller);
|
||||
character_controller = NULL;
|
||||
|
||||
compound = NULL;
|
||||
motion_state = NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletPhysicItem::SetGravity(const Vector4 &g)
|
||||
{
|
||||
if (rigid_body)
|
||||
rigid_body->setGravity(btVector3(g.x, g.y, g.z));
|
||||
}
|
||||
Vector4 BulletPhysicItem::GetGravity() const
|
||||
{
|
||||
if (!rigid_body)
|
||||
return Vector4(0, 0, 0);
|
||||
btVector3 g = rigid_body->getGravity();
|
||||
return Vector4(g.x(), g.y(), g.z());
|
||||
}
|
||||
void BulletPhysicItem::ApplyImpulse(const Vector4 &I, const Vector4 *p)
|
||||
{
|
||||
if (!rigid_body)
|
||||
return;
|
||||
|
||||
SetSleeping(false);
|
||||
|
||||
if (p && (I.Len() > 0.0001))
|
||||
{
|
||||
btVector3 l(p->x, p->y, p->z);
|
||||
btVector3 J(I.x, I.y, I.z);
|
||||
btScalar k = rigid_body->computeImpulseDenominator(l, J.normalized());
|
||||
rigid_body->applyImpulse(J / k, l - rigid_body->getCenterOfMassPosition());
|
||||
}
|
||||
else
|
||||
{
|
||||
btVector3 J(I.x, I.y, I.z);
|
||||
rigid_body->applyCentralImpulse(J / rigid_body->getInvMass());
|
||||
}
|
||||
}
|
||||
void BulletPhysicItem::ApplyForce(const Vector4 &F, const Vector4 *p)
|
||||
{
|
||||
if (!rigid_body)
|
||||
return;
|
||||
|
||||
SetSleeping(false);
|
||||
if (p)
|
||||
rigid_body->applyForce(btVector3(F.x, F.y, F.z), btVector3(p->x, p->y, p->z) - rigid_body->getCenterOfMassPosition());
|
||||
else rigid_body->applyCentralForce(btVector3(F.x, F.y, F.z));
|
||||
}
|
||||
void BulletPhysicItem::ApplyTorque(const Vector4 &T)
|
||||
{
|
||||
if (rigid_body)
|
||||
rigid_body->applyTorque(rigid_body->getCenterOfMassTransform().getBasis() * btVector3(T.x, T.y, T.z));
|
||||
}
|
||||
void BulletPhysicItem::SetAngularVelocity(const Vector4 &w)
|
||||
{
|
||||
if (rigid_body)
|
||||
rigid_body->setAngularVelocity(btVector3(w.x, w.y, w.z));
|
||||
}
|
||||
Vector4 BulletPhysicItem::GetAngularVelocity() const
|
||||
{
|
||||
if (!rigid_body)
|
||||
return Vector4(0, 0, 0);
|
||||
const btVector3 &v = rigid_body->getAngularVelocity();
|
||||
return Vector4(v.x(), v.y(), v.z());
|
||||
}
|
||||
void BulletPhysicItem::SetLinearVelocity(const Vector4 &v)
|
||||
{
|
||||
if (rigid_body)
|
||||
rigid_body->setLinearVelocity(btVector3(v.x, v.y, v.z));
|
||||
}
|
||||
Vector4 BulletPhysicItem::GetLinearVelocity() const
|
||||
{
|
||||
if (!rigid_body)
|
||||
return Vector4(0, 0, 0);
|
||||
const btVector3 &v = rigid_body->getLinearVelocity();
|
||||
return Vector4(v.x(), v.y(), v.z());
|
||||
}
|
||||
Vector4 BulletPhysicItem::GetLocalPointVelocity(const Vector4 &p) const
|
||||
{
|
||||
if (!rigid_body)
|
||||
return Vector4(0, 0, 0);
|
||||
btVector3 v = rigid_body->getVelocityInLocalPoint(rigid_body->getCenterOfMassTransform().getBasis() * btVector3(p.x, p.y, p.z));
|
||||
return Vector4(v.x(), v.y(), v.z());
|
||||
}
|
||||
Vector4 BulletPhysicItem::GetWorldPointVelocity(const Vector4 &wp) const
|
||||
{
|
||||
if (!rigid_body)
|
||||
return Vector4(0, 0, 0);
|
||||
btVector3 v = rigid_body->getVelocityInLocalPoint(btVector3(wp.x, wp.y, wp.z) - rigid_body->getCenterOfMassPosition());
|
||||
return Vector4(v.x(), v.y(), v.z());
|
||||
}
|
||||
Vector4 BulletPhysicItem::GetCenterOfMass() const
|
||||
{
|
||||
if (!rigid_body)
|
||||
return Vector4(0, 0, 0);
|
||||
btVector3 p = rigid_body->getCenterOfMassPosition();
|
||||
return Vector4(p.x(), p.y(), p.z());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
BulletPhysicItem::BulletPhysicItem(btDiscreteDynamicsWorld *w)
|
||||
{
|
||||
btworld = w;
|
||||
|
||||
center.Set(0, 0, 0);
|
||||
scale.Set(1, 1, 1);
|
||||
}
|
||||
BulletPhysicItem::~BulletPhysicItem()
|
||||
{
|
||||
DeleteBody();
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
345
include/modules/physic_bullet/bullet_world.cpp
Normal file
345
include/modules/physic_bullet/bullet_world.cpp
Normal file
@ -0,0 +1,345 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "physic_bullet/bullet_world.h"
|
||||
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
|
||||
#include "physic_bullet/bullet_item.h"
|
||||
#include "physic_bullet/bullet_constraint.h"
|
||||
#include "physic_bullet/bullet_debug.h"
|
||||
#include "core/geometry.h"
|
||||
#include "metafile/nml_object.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
PhysicItem *BulletWorld::NewItem()
|
||||
{ return new BulletPhysicItem(world); }
|
||||
PhysicConstraint *BulletWorld::NewConstraint()
|
||||
{ return new BulletConstraint(world); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
BulletConvex *BulletWorld::LoadConvex(const char *_name)
|
||||
{
|
||||
String name(_name);
|
||||
|
||||
// Check cache.
|
||||
ListForeachPtr(BulletConvex *, convex, convex_cache)
|
||||
if (convex->name == name)
|
||||
return convex;
|
||||
|
||||
// Load geometry.
|
||||
AutoPtr <Core::Geometry> g(new Core::Geometry);
|
||||
if (!NML::LoadFromFile(*g, name))
|
||||
return NULL;
|
||||
|
||||
// Setup convex.
|
||||
BulletConvex *bullet_convex = new BulletConvex;
|
||||
if (!bullet_convex)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate bullet convex.\n", NULL)
|
||||
|
||||
Array <btScalar> bt_vtx(g->vtx.GetCount() * 3);
|
||||
btScalar *p_bt_vtx = bt_vtx.c_ptr();
|
||||
|
||||
Vector4 gcenter(0, 0, 0);
|
||||
for (uint n = 0; n < g->vtx.GetCount(); ++n)
|
||||
{
|
||||
gcenter += g->vtx[n];
|
||||
*p_bt_vtx++ = g->vtx[n].x;
|
||||
*p_bt_vtx++ = g->vtx[n].y;
|
||||
*p_bt_vtx++ = g->vtx[n].z;
|
||||
}
|
||||
|
||||
bullet_convex->name = name;
|
||||
bullet_convex->center = (gcenter / (float)g->vtx.GetCount());
|
||||
bullet_convex->convex = new btConvexHullShape(bt_vtx.c_ptr(), g->vtx.GetCount(), 3 * sizeof(btScalar));
|
||||
convex_cache.Add(bullet_convex);
|
||||
|
||||
return bullet_convex;
|
||||
}
|
||||
BulletMesh *BulletWorld::LoadMesh(const char *_name, const char *_suffix)
|
||||
{
|
||||
String name(_name), suffix(_suffix);
|
||||
|
||||
// Check cache.
|
||||
ListForeachPtr(BulletMesh *, mesh, mesh_cache)
|
||||
if ((mesh->name == name) && (mesh->suffix == suffix))
|
||||
{
|
||||
__LOG_V__ << "Reusing cached Bullet btMesh for " << _name << " (suffix: " << _suffix << ").\n";
|
||||
return mesh;
|
||||
}
|
||||
|
||||
// Load bullet mesh.
|
||||
AutoPtr <Core::Geometry> g(new Core::Geometry);
|
||||
if (g.IsNull())
|
||||
return NULL;
|
||||
|
||||
g->name = name;
|
||||
if (!NML::LoadFromFile(*g, name))
|
||||
return NULL;
|
||||
|
||||
if (!g->vtx.GetCount() || !g->pol.GetCount())
|
||||
__ERR__(__LOG_E__ << "No geometry data in '" << g->name << "' to build collision shape.\n", NULL)
|
||||
|
||||
BulletMesh *bullet_mesh = new BulletMesh;
|
||||
if (!bullet_mesh)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate bullet mesh.\n", NULL)
|
||||
|
||||
int triangle_count = g->GetTriangleCount();
|
||||
|
||||
bullet_mesh->bt_vtx.Allocate(g->vtx.GetCount() * 3);
|
||||
btScalar *p_bt_vtx = bullet_mesh->bt_vtx;
|
||||
bullet_mesh->bt_idx.Allocate(triangle_count * 3);
|
||||
int *p_bt_idx = bullet_mesh->bt_idx;
|
||||
|
||||
Vector4 gcenter(0, 0, 0);
|
||||
for (uint n = 0; n < g->vtx.GetCount(); ++n)
|
||||
{
|
||||
gcenter += g->vtx[n];
|
||||
*p_bt_vtx++ = g->vtx[n].x;
|
||||
*p_bt_vtx++ = g->vtx[n].y;
|
||||
*p_bt_vtx++ = g->vtx[n].z;
|
||||
}
|
||||
bullet_mesh->center = gcenter / (float)g->vtx.GetCount();
|
||||
|
||||
// Triangulate geometry on the fly, transfer material indices.
|
||||
bullet_mesh->bt_mat.Allocate(g->material_table.GetCount());
|
||||
for (uint n = 0; n < g->material_table.GetCount(); ++n)
|
||||
bullet_mesh->bt_mat[n] = g->material_table[n].name;
|
||||
|
||||
bullet_mesh->bt_id_mat.Allocate(triangle_count);
|
||||
ushort *p_bt_id_mat = bullet_mesh->bt_id_mat;
|
||||
|
||||
for (uint n = 0; n < g->pol.GetCount(); ++n)
|
||||
for (int p = 1; p < (g->pol[n].vtx_count - 1); ++p)
|
||||
{
|
||||
*p_bt_idx++ = g->pol[n].binding[0];
|
||||
*p_bt_idx++ = g->pol[n].binding[p];
|
||||
*p_bt_idx++ = g->pol[n].binding[p + 1];
|
||||
*p_bt_id_mat++ = g->pol[n].material;
|
||||
}
|
||||
|
||||
bullet_mesh->name = name;
|
||||
bullet_mesh->suffix = suffix;
|
||||
bullet_mesh->mesh_interface = new btTriangleIndexVertexArray(triangle_count, bullet_mesh->bt_idx, 3 * sizeof(int), g->vtx.GetCount(), bullet_mesh->bt_vtx, 3 * sizeof(btScalar));
|
||||
bullet_mesh->mesh = new btBvhTriangleMeshShape(bullet_mesh->mesh_interface, true);
|
||||
|
||||
mesh_cache.Add(bullet_mesh);
|
||||
|
||||
return bullet_mesh;
|
||||
}
|
||||
void BulletWorld::ClearConvexMeshCache()
|
||||
{
|
||||
convex_cache.Clear();
|
||||
mesh_cache.Clear();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool BulletWorld::HasDebugger() const
|
||||
{ return debug_draw.IsValid(); }
|
||||
void BulletWorld::CreateDebugger(Renderer *renderer)
|
||||
{
|
||||
debug_draw = renderer ? new BulletDebugDraw(*renderer) : NULL;
|
||||
if (world)
|
||||
world->setDebugDrawer(debug_draw);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void bullet_pretick_callback(btDynamicsWorld *world, btScalar timeStep)
|
||||
{
|
||||
BulletWorld *physic_world = (BulletWorld *)world->getWorldUserInfo();
|
||||
if (physic_world->GetWorldInterface())
|
||||
physic_world->GetWorldInterface()->PhysicStep(timeStep, true);
|
||||
}
|
||||
static void bullet_posttick_callback(btDynamicsWorld *world, btScalar timeStep)
|
||||
{
|
||||
BulletWorld *physic_world = (BulletWorld *)world->getWorldUserInfo();
|
||||
if (physic_world->GetWorldInterface())
|
||||
physic_world->GetWorldInterface()->PhysicStep(timeStep, false);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletWorld::DrawDebug(Renderer &, Camera *c, RasterFont *f, bool xray_first_pass)
|
||||
{
|
||||
if (BulletDebugDraw *dd = (BulletDebugDraw *)world->getDebugDrawer())
|
||||
{
|
||||
dd->camera = c;
|
||||
dd->raster_font = f;
|
||||
dd->SetDebugMode(btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits | btIDebugDraw::DBG_DrawContactPoints);
|
||||
// dd->SetDebugMode(btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_FastWireframe);
|
||||
dd->SetXRayFirstPass(xray_first_pass);
|
||||
|
||||
world->debugDrawWorld();
|
||||
dd->Flush();
|
||||
}
|
||||
}
|
||||
uint BulletWorld::GetCollisionPairCount()
|
||||
{ return world->getDispatcher()->getNumManifolds(); }
|
||||
bool BulletWorld::GetCollisionPair(uint n, CollisionPair &pair)
|
||||
{
|
||||
btPersistentManifold *manifold = world->getDispatcher()->getInternalManifoldPointer()[n];
|
||||
if (!manifold || !manifold->getNumContacts()) // Manifolds are valid as long as the bodies overlap in the broadphase.
|
||||
return false;
|
||||
|
||||
pair.a = (PhysicItem *)((btRigidBody *)manifold->getBody0())->getUserPointer();
|
||||
pair.b = (PhysicItem *)((btRigidBody *)manifold->getBody1())->getUserPointer();
|
||||
|
||||
pair.contact_count = 0;
|
||||
for (int i = 0; (i < manifold->getNumContacts()) && (i < 4); ++i)
|
||||
{
|
||||
btVector3 p = manifold->getContactPoint(i).getPositionWorldOnB();
|
||||
pair.contact[i].Set(p.x(), p.y(), p.z());
|
||||
btVector3 n = manifold->getContactPoint(i).m_normalWorldOnB;
|
||||
pair.normal[i].Set(n.x(), n.y(), n.z());
|
||||
|
||||
pair.contact_count++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool BulletWorld::Create()
|
||||
{
|
||||
collision_config = new btDefaultCollisionConfiguration();
|
||||
|
||||
#if __ENABLE_BULLET_MULTITHREAD__
|
||||
thread_support_collision = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo("Bullet Collision", processCollisionTask, createCollisionLocalStoreMemory, __BULLET_THREAD_COUNT__));
|
||||
dispatcher = new SpuGatheringCollisionDispatcher(thread_support_collision, __BULLET_THREAD_COUNT__, collision_config);
|
||||
#else
|
||||
dispatcher = new btCollisionDispatcher(collision_config);
|
||||
#endif
|
||||
|
||||
broadphase = new btDbvtBroadphase();
|
||||
broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(pair_callback = new btGhostPairCallback);
|
||||
|
||||
solver = new btSequentialImpulseConstraintSolver;
|
||||
world = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collision_config);
|
||||
world->setInternalTickCallback(bullet_pretick_callback, (void *)this, true);
|
||||
world->setInternalTickCallback(bullet_posttick_callback, (void *)this, false);
|
||||
|
||||
// world->getSolverInfo().m_numIterations = 10;
|
||||
// world->getDispatchInfo().m_enableSPU = true;
|
||||
world->getSolverInfo().m_solverMode = SOLVER_SIMD + SOLVER_USE_WARMSTARTING;// + SOLVER_RANDMIZE_ORDER;
|
||||
// world->getSolverInfo().m_splitImpulse = 1;
|
||||
// world->getSolverInfo().m_splitImpulsePenetrationThreshold = 0.2;
|
||||
|
||||
world->setDebugDrawer(debug_draw);
|
||||
return true;
|
||||
}
|
||||
void BulletWorld::Delete()
|
||||
{
|
||||
ClearConvexMeshCache();
|
||||
|
||||
collision_config = NULL;
|
||||
dispatcher = NULL;
|
||||
broadphase = NULL;
|
||||
solver = NULL;
|
||||
world = NULL;
|
||||
#if __ENABLE_BULLET_MULTITHREAD__
|
||||
thread_support_collision = NULL;
|
||||
#endif
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BulletWorld::Step(const GS::Time &dt)
|
||||
{
|
||||
ScopedBenchmark bench(bench_step);
|
||||
|
||||
#if 1
|
||||
substep_dt -= dt.toSec();
|
||||
|
||||
int limit = 4;
|
||||
while (substep_dt < 0)
|
||||
{
|
||||
world->stepSimulation(GetTimestep(), 0, GetTimestep());
|
||||
substep_dt += GetTimestep();
|
||||
|
||||
if (--limit <= 0)
|
||||
{
|
||||
substep_dt = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
world->stepSimulation(dt, 12, GetTimestep());
|
||||
#endif
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool BulletWorld::Raytrace(const Vector4 &s, const Vector4 &d, PhysicTrace &hit, int collision_mask, int shape_mask, float max_distance)
|
||||
{
|
||||
struct ClosestRayResultWithTriangleIndexCallback : public btCollisionWorld::ClosestRayResultCallback
|
||||
{
|
||||
ClosestRayResultWithTriangleIndexCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld) : ClosestRayResultCallback(rayFromWorld, rayToWorld) {}
|
||||
|
||||
int m_TriangleIndex;
|
||||
int m_shapePart;
|
||||
|
||||
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace)
|
||||
{
|
||||
if (rayResult.m_localShapeInfo)
|
||||
{
|
||||
m_TriangleIndex = rayResult.m_localShapeInfo->m_triangleIndex;
|
||||
m_shapePart = rayResult.m_localShapeInfo->m_shapePart;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_TriangleIndex = -1;
|
||||
m_shapePart = -1;
|
||||
}
|
||||
return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
|
||||
}
|
||||
};
|
||||
|
||||
Vector4 e = s + d * (max_distance > 0 ? max_distance : 5000.f);
|
||||
btVector3 from(s.x, s.y, s.z), to(e.x, e.y, e.z);
|
||||
|
||||
ClosestRayResultWithTriangleIndexCallback trace(from, to);
|
||||
trace.m_collisionFilterGroup = btBroadphaseProxy::AllFilter;
|
||||
trace.m_collisionFilterMask = (short)collision_mask;
|
||||
world->rayTest(from, to, trace);
|
||||
if (!trace.hasHit())
|
||||
return false;
|
||||
|
||||
hit.p.Set(trace.m_hitPointWorld.x(), trace.m_hitPointWorld.y(), trace.m_hitPointWorld.z());
|
||||
hit.n.Set(trace.m_hitNormalWorld.x(), trace.m_hitNormalWorld.y(), trace.m_hitNormalWorld.z());
|
||||
hit.i = (PhysicItem *)trace.m_collisionObject->getUserPointer();
|
||||
|
||||
if (BulletPhysicItem *bi = (BulletPhysicItem *)hit.i)
|
||||
if ((trace.m_shapePart >= 0) && ((uint)trace.m_shapePart < bi->shapes.GetCount()))
|
||||
if (BulletMesh *mesh = bi->shapes[trace.m_shapePart].mesh.c_ptr())
|
||||
if (uint(trace.m_TriangleIndex) < mesh->bt_id_mat.GetCount())
|
||||
hit.m = mesh->bt_mat[mesh->bt_id_mat[trace.m_TriangleIndex]];
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void *bulletAlloc(size_t s) { return MemAllocPhysics::Alloc(s, Alloc::Physics); }
|
||||
static void bulletFree(void *p) { MemAllocPhysics::Delete(p, Alloc::Physics); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
BulletWorld::BulletWorld()
|
||||
{
|
||||
btAlignedAllocSetCustom(bulletAlloc, bulletFree);
|
||||
substep_dt = 0;
|
||||
}
|
||||
BulletWorld::~BulletWorld()
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
152
include/modules/pict_io_jpeglib/pict_jpeglib_codec.cpp
Normal file
152
include/modules/pict_io_jpeglib/pict_jpeglib_codec.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include "pict_io_jpeglib/pict_jpeglib_codec.h"
|
||||
#include "picture/pict.h"
|
||||
#include "container/narray.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
#if 1
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int JpgLoad_ansic(void *buf, int len, char **output, unsigned int *width, unsigned int *height);
|
||||
int JpgSave_ansic(char *dst, int dst_len, int *size, int qual, char *buf, unsigned int w, unsigned int h);
|
||||
void JpgFree_ansic(char **p);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void FetchHCoef(char *bf, int w, int /*h*/, int x, int y, float *cf)
|
||||
{
|
||||
bf += y * w * 3;
|
||||
for ( int p = (x - 2); p < (x + 2); p++ )
|
||||
{
|
||||
int op = p;
|
||||
if ( op < 0 ) op = 0;
|
||||
else if ( op >= w ) op = w - 1;
|
||||
*cf++ = (float)((unsigned char)bf[op * 3]);
|
||||
}
|
||||
}
|
||||
float Spline4Inter(float t, float *cf)
|
||||
{
|
||||
float v = cf[1]+0.5f*t*(cf[2]-cf[0]+t*(cf[2]+cf[1]*(-2.0f)+cf[0]+t*((cf[2]-cf[1])*9.0f+(cf[0]-cf[3])*3.f+t*((cf[1]-cf[2])*15.f+(cf[3]-cf[0])*5.f+t*((cf[2]-cf[1])*6.f+(cf[0]-cf[3])*2.f)))));
|
||||
if ( v < 0.f )
|
||||
v = 0.f;
|
||||
else if ( v > 255.f )
|
||||
v = 255.f;
|
||||
return v;
|
||||
}
|
||||
char *RgbResize(char *rgb, int ow, int oh, int w, int h)
|
||||
{
|
||||
char *nr = new char[w * h * 3], *pr;
|
||||
int x, y, c, v;
|
||||
float hc[4], vc[4];
|
||||
float px, py, dx, dy;
|
||||
|
||||
dx = (float)ow / (float)w;
|
||||
dy = (float)oh / (float)h;
|
||||
|
||||
py = 0.f;
|
||||
pr = nr;
|
||||
for ( y = 0; y < h; y++ )
|
||||
{
|
||||
px = 0.f;
|
||||
for ( x = 0; x < w; x++ )
|
||||
{
|
||||
for ( c = 0; c < 3; c++ )
|
||||
{
|
||||
float *pvc = vc;
|
||||
for ( v = -2; v < 2; v++ )
|
||||
{
|
||||
int sy = v + (int)py;
|
||||
if ( sy < 0 ) sy = 0;
|
||||
if ( sy >= oh ) sy = oh - 1;
|
||||
FetchHCoef(rgb + c, ow, oh, (int)px, sy, hc);
|
||||
*pvc++ = Spline4Inter(px - ((int)px), hc);
|
||||
}
|
||||
*pr++ = (unsigned char)Spline4Inter(py - ((int)py), vc);
|
||||
}
|
||||
px += dx;
|
||||
}
|
||||
py += dy;
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void JpeglibCppInterfaceFree(char **p)
|
||||
{ JpgFree_ansic(p); }
|
||||
int JpeglibCppInterfaceLoad(void *f, int l, char **o, unsigned int *w, unsigned int *h)
|
||||
{ return JpgLoad_ansic(f, l, o, w, h); }
|
||||
int JpeglibCppInterfaceSave(char *dst, int dst_len, int *size, int q, char *b, unsigned int w, unsigned int h)
|
||||
{ return JpgSave_ansic(dst, dst_len, size, q, b, w, h); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool PictureJpeglibCodec::Load(IO::Handle &handle, Picture &picture)
|
||||
{
|
||||
uchar header[2];
|
||||
handle.Rewind();
|
||||
if (handle.Read(header, 2) != 2)
|
||||
return false;
|
||||
if ((header[0] != 0xff) || (header[1] != 0xd8))
|
||||
return false;
|
||||
|
||||
// SOI marker found, good to go.
|
||||
size_t size = handle.GetSize();
|
||||
Array <void *> buffer((uint)size);
|
||||
if (!buffer)
|
||||
return false;
|
||||
|
||||
handle.Rewind();
|
||||
handle.Read(buffer, size);
|
||||
|
||||
uint width, height;
|
||||
char *c_data = NULL;
|
||||
|
||||
if (JpeglibCppInterfaceLoad(buffer, (int)size, &c_data, &width, &height))
|
||||
{
|
||||
// Transfer C data to a C++ allocation.
|
||||
picture.AllocAs(width, height);
|
||||
if (uchar *data = picture.GetData())
|
||||
{
|
||||
uchar *j_data = (uchar *)c_data;
|
||||
for (uint h = 0; h < height; ++h)
|
||||
for (uint w = 0; w < width; ++w)
|
||||
{
|
||||
data[0] = j_data[2];
|
||||
data[1] = j_data[1];
|
||||
data[2] = j_data[0];
|
||||
data[3] = j_data[3];
|
||||
j_data += 4;
|
||||
data += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Drop C data.
|
||||
JpeglibCppInterfaceFree(&c_data);
|
||||
}
|
||||
return asbool(picture.GetData());
|
||||
}
|
||||
bool PictureJpeglibCodec::Save(IO::Handle &handle, const Picture &picture)
|
||||
{
|
||||
// FIXME this is stupid.
|
||||
Array <char> dst(5000000);
|
||||
if (!dst)
|
||||
return false;
|
||||
|
||||
int size = 0;
|
||||
if (!JpeglibCppInterfaceSave(&dst[0], (uint)dst.GetSize(), &size, 100, (char *)picture.GetData(), picture.GetWidth(), picture.GetHeight()))
|
||||
return false;
|
||||
|
||||
return handle.Write(dst, size) == (size_t)size;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
53
include/modules/pict_io_stb/pict_stb_codec.cpp
Normal file
53
include/modules/pict_io_stb/pict_stb_codec.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include "pict_io_stb/pict_stb_codec.h"
|
||||
#include "picture/pict.h"
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "container/narray.h"
|
||||
#include "memory/memory.h"
|
||||
#include "log/log.h"
|
||||
|
||||
#define STBI_NO_STDIO
|
||||
#include "stb_image.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static int n_stb_read_h(void *user, char *data, int size)
|
||||
{ return ((IO::Handle *)user)->Read(data, size); }
|
||||
static void n_stb_skip_h(void *user, unsigned n)
|
||||
{ ((IO::Handle *)user)->Seek(n); }
|
||||
static int n_stb_eof_h(void *user)
|
||||
{ return ((IO::Handle *)user)->IsEOF() ? 1 : 0; }
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool PictureSTBCodec::Load(IO::Handle &handle, Picture &picture)
|
||||
{
|
||||
handle.Rewind();
|
||||
|
||||
stbi_io_callbacks cb;
|
||||
cb.read = &n_stb_read_h;
|
||||
cb.skip = &n_stb_skip_h;
|
||||
cb.eof = &n_stb_eof_h;
|
||||
|
||||
/*
|
||||
Swizzle and transfer to C++ allocation.
|
||||
Watch the memory peak!...
|
||||
*/
|
||||
int comp, width, height;
|
||||
if (char *c_data = (char *)stbi_load_from_callbacks(&cb, &handle, &width, &height, &comp, STBI_rgb_alpha))
|
||||
{
|
||||
picture.AllocAs(width, height);
|
||||
if (char *p_data = (char *)picture.GetData())
|
||||
Memory::Copy(p_data, c_data, width * height * 4);
|
||||
stbi_image_free(c_data);
|
||||
}
|
||||
return asbool(picture.GetData());
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
748
include/modules/raytracer/raytracer_core.cpp
Normal file
748
include/modules/raytracer/raytracer_core.cpp
Normal file
@ -0,0 +1,748 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "raytracer/raytracer_core.h"
|
||||
#include "raytracer/raytracer_job.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/mcamera.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "rand/rand.h"
|
||||
#include "platform.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::Raytrace;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
float Raytracer::Fresnel(const Vector4 &v, const Vector4 &np, float eta)
|
||||
{
|
||||
float const r0 = Math::Pow(1.0f - eta, 2.0f) / Math::Pow(1.0f + eta, 2.0f);
|
||||
// Light vector and normal are assumed to be normalized.
|
||||
return Types::Clamp <float> (r0 + (1.0f - r0) * Math::Pow(1 - Types::Abs(v.Dot(np)), 5.0f), 0.0f, 1.0f);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
float Raytracer::ShadowFeel(const Vector4 &s, const Vector4 &d, float l, int r)
|
||||
{
|
||||
float k_shadow = 1;
|
||||
|
||||
if (configuration.trace_transparency)
|
||||
{
|
||||
if (!r)
|
||||
return k_shadow;
|
||||
|
||||
// Get closest hit.
|
||||
Trace trace;
|
||||
scene_shadow_tree.RaytraceScene(trace, s, d, l);
|
||||
statistics.ray_count++;
|
||||
statistics.tri_test += trace.tri_test;
|
||||
|
||||
if (trace.has_i && (trace.i_t > 0))
|
||||
{
|
||||
// Check opacity.
|
||||
float opacity = SampleMaterialOpacity(trace);
|
||||
|
||||
// Early exit on fully opaque hit.
|
||||
if (opacity == 1)
|
||||
return 0;
|
||||
k_shadow = 1 - opacity;
|
||||
|
||||
// Recurse.
|
||||
Vector4 offset_pi = trace.s + trace.d * (trace.i_t + Units::Mm(1));
|
||||
k_shadow *= ShadowFeel(offset_pi, trace.d, l - Vector4::Dist(trace.s, offset_pi), --r);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Any hit within range will do.
|
||||
Trace trace(false);
|
||||
scene_shadow_tree.RaytraceScene(trace, s, d, l);
|
||||
|
||||
if (trace.has_i && (trace.i_t > 0))
|
||||
return 0; // Occluded.
|
||||
}
|
||||
|
||||
return k_shadow;
|
||||
}
|
||||
void Raytracer::ComputeRadiance(Trace &trace, Color &o, Bounce &bounce)
|
||||
{
|
||||
bool use_fixed_function = trace.m->shader.IsEmpty();
|
||||
bool blend_additive = trace.m->blendop == Material::Blend_Add;
|
||||
|
||||
// Evaluate material alpha.
|
||||
float alpha;
|
||||
if (use_fixed_function)
|
||||
alpha = SampleMaterialOpacity(trace);
|
||||
else alpha = SampleMaterialSink(trace, ShaderTree::SinkOpacity).x;
|
||||
alpha *= trace.o->opacity;
|
||||
|
||||
// Compute direct lighting, if the material does not care about the alpha test, or if the material cares about it and its alpha is up to the threshold.
|
||||
if (!(trace.m->renderword & Material::Render_AlphaTest) || alpha > trace.m->athreshold)
|
||||
{
|
||||
// Evaluate material glossiness.
|
||||
float glossiness;
|
||||
if (use_fixed_function)
|
||||
glossiness = trace.m->glossiness;
|
||||
else glossiness = SampleMaterialSink(trace, ShaderTree::SinkGlossiness).x;
|
||||
|
||||
// Evaluate light contribution.
|
||||
Color l_diff(0, 0, 0), l_spec(0, 0, 0);
|
||||
Vector4 offset_pi = trace.pi + trace.n * Units::Mm(1.f);
|
||||
|
||||
for (uint n = 0; n < lgt.GetCount(); ++n)
|
||||
if (S3D::MLight *l = lgt[n].l)
|
||||
{
|
||||
Core::Light *light = (Core::Light *)l;
|
||||
float k_shadow = 1.f;
|
||||
|
||||
if ((light->shadow != Core::Light::Shadow_None) && configuration.trace_shadow)
|
||||
{
|
||||
Vector4 d;
|
||||
|
||||
switch (light->model)
|
||||
{
|
||||
default:
|
||||
case Core::Light::Model_Point:
|
||||
d = light->GetMatrix().GetRow(3) - offset_pi;
|
||||
break;
|
||||
|
||||
case Core::Light::Model_Linear:
|
||||
d = light->GetMatrix().GetRow(2).Reversed() * light->clip_distance;
|
||||
break;
|
||||
}
|
||||
|
||||
if (d.Dot(trace.n) > 0)
|
||||
{
|
||||
float l = d.Len();
|
||||
d /= l;
|
||||
|
||||
k_shadow = ShadowFeel(offset_pi, d, l, configuration.trace_shadow_transparency_max_recursion);
|
||||
if (!k_shadow)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute contribution.
|
||||
float k_d, k_s;
|
||||
if (light->SampleEnergy(trace.pi, trace.n, &k_d, &k_s, &trace.d, glossiness))
|
||||
{
|
||||
l_diff += light->diffuse_color * light->diffuse_intensity * k_d * k_shadow;
|
||||
l_spec += light->specular_color * light->specular_intensity * k_s * k_shadow;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute indirect lighting.
|
||||
Color l_indirect(0, 0, 0), ambient(0, 0, 0);
|
||||
|
||||
if (configuration.trace_gi && bounce.indirect)
|
||||
{
|
||||
bounce.indirect--;
|
||||
|
||||
Spread &mc = monte_carlo[Random::Rand(32)];
|
||||
Matrix3 nm(Matrix3::FromOrthonormalBasis(trace.n));
|
||||
Color l;
|
||||
|
||||
// divide by the number of bounce, to avoid full bounce each time.
|
||||
int count_spread = mc.spread.GetCount();
|
||||
if (configuration.indirect_gi_bounce - bounce.indirect != 0)
|
||||
count_spread /= configuration.indirect_gi_bounce - bounce.indirect + 1;
|
||||
count_spread = Types::Max(count_spread, 1);
|
||||
|
||||
for (int n = 0; n < count_spread; ++n)
|
||||
{
|
||||
Bounce ibounce;
|
||||
|
||||
ibounce.indirect = bounce.indirect;
|
||||
ibounce.reflection = 0;
|
||||
ibounce.refraction = 0;
|
||||
|
||||
Raytrace(RayGrid(offset_pi, mc.spread[n] * nm), l, ibounce);
|
||||
l_indirect += l;
|
||||
}
|
||||
l_indirect /= (float)count_spread;
|
||||
}
|
||||
else
|
||||
ambient = (configuration.gi_use_ambient || !configuration.trace_gi) ? scene->ambient_color * scene->ambient_intensity : Vector4(0.f, 0.f, 0.f);
|
||||
|
||||
// Compute ambient occlusion.
|
||||
float ambient_occlusion = 1.0f;
|
||||
|
||||
if ((alpha >= 1.0f) && configuration.ao_activate)
|
||||
{
|
||||
Spread &mc = monte_carlo[Random::Rand(32)];
|
||||
Matrix3 nm(Matrix3::FromOrthonormalBasis(trace.n));
|
||||
|
||||
float countouch = 0.0f;
|
||||
float lengthmax = configuration.ao_length;
|
||||
float divlengthmaxsq = 1.0f / lengthmax;
|
||||
|
||||
for (uint n = 0; n < mc.spread.GetCount(); ++n)
|
||||
{
|
||||
// Create the direction vector from the normal of the point with a bit of random.
|
||||
Trace traceOcclusion;
|
||||
Vector4 start(trace.pi + mc.spread[n] * nm * Units::Mm(1.f));
|
||||
/*
|
||||
nVector DirVect(mc.spread[n] * nm);
|
||||
scene_tree.RaytraceScene(traceOcclusion, start, DirVect, lengthmax);
|
||||
|
||||
// check the raytrace pass if the alpha of the map and continue to raytrace then
|
||||
float alphaOcclusion = 0.0f;
|
||||
float current_length = 0.0f;
|
||||
|
||||
while(alphaOcclusion < 1.0f && current_length < lengthmax &&
|
||||
traceOcclusion.has_i && (traceOcclusion.i_t > 0.0f))
|
||||
{
|
||||
current_length += traceOcclusion.i_t;
|
||||
|
||||
// Compute intersection point and fetch material.
|
||||
traceOcclusion.pi = traceOcclusion.s + traceOcclusion.d * traceOcclusion.i_t;
|
||||
traceOcclusion.m = traceOcclusion.g->material_table[traceOcclusion.g->pol[traceOcclusion.ip].material];
|
||||
|
||||
bool use_fixed_functionOcclusion = trace.m->shader_tree == NULL ? true : false;
|
||||
|
||||
// Evaluate material alpha.
|
||||
float TempAlphaOcclusion = 0.0f;
|
||||
|
||||
if (use_fixed_functionOcclusion)
|
||||
TempAlphaOcclusion = SampleMaterialOpacity(traceOcclusion);
|
||||
else TempAlphaOcclusion = SampleMaterialSink(traceOcclusion, nShaderTree::SinkOpacity).x;
|
||||
alphaOcclusion += TempAlphaOcclusion*traceOcclusion.o->opacity;
|
||||
|
||||
if(alphaOcclusion < 1.0f && current_length < lengthmax)
|
||||
scene_tree.RaytraceScene(traceOcclusion, traceOcclusion.pi + DirVect* Mm(1), DirVect, lengthmax - current_length);
|
||||
}
|
||||
|
||||
if(alphaOcclusion > 1.0f)
|
||||
alphaOcclusion = 1.0f;
|
||||
|
||||
if (alphaOcclusion > 0)
|
||||
countouch += (1.0f - Types::Clamp(current_length * divlengthmaxsq, 0.0f, 1.0f))* alphaOcclusion;
|
||||
*/
|
||||
scene_tree.RaytraceScene(traceOcclusion, start, mc.spread[n] * nm, lengthmax);
|
||||
|
||||
if (traceOcclusion.has_i && (traceOcclusion.i_t > 0.0f))
|
||||
countouch += 1.0f - Types::Clamp(traceOcclusion.i_t * divlengthmaxsq, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
if (countouch > 0.0f)
|
||||
ambient_occlusion = 1.0f - countouch / mc.spread.GetCount();
|
||||
ambient_occlusion = Types::Clamp(ambient_occlusion);
|
||||
}
|
||||
|
||||
// Sample attributes.
|
||||
Color diffuse, specular, self;
|
||||
|
||||
if (use_fixed_function)
|
||||
{
|
||||
// Gather attributes.
|
||||
diffuse = SampleMaterialAttribute(trace, Channel_Diffuse);
|
||||
specular = SampleMaterialAttribute(trace, Channel_Specular);
|
||||
self = SampleMaterialAttribute(trace, Channel_SelfIllum);
|
||||
|
||||
// Vertex color.
|
||||
if (trace.m->GetChannelStage(Channel_Light))
|
||||
{
|
||||
Color color = SampleMaterialAttribute(trace, Channel_Light);
|
||||
diffuse *= color;
|
||||
specular *= color;
|
||||
}
|
||||
else if (trace.m->renderword & Material::Render_VertexColor)
|
||||
{
|
||||
Color color = SampleGeometryAttribute(trace, GeometryVertexColor);
|
||||
diffuse *= color;
|
||||
specular *= color;
|
||||
}
|
||||
|
||||
// Environment mapping.
|
||||
if (trace.m->GetChannelStage(Channel_Reflection))
|
||||
{
|
||||
Color color = SampleMaterialAttribute(trace, Channel_Reflection);
|
||||
switch (trace.m->GetChannelStage(Channel_Reflection)->op)
|
||||
{
|
||||
case Material::Operator_Multiply:
|
||||
diffuse *= color;
|
||||
break;
|
||||
|
||||
case Material::Operator_Default:
|
||||
case Material::Operator_Add:
|
||||
diffuse += color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
diffuse = SampleMaterialSink(trace, ShaderTree::SinkDiffuse);
|
||||
specular = SampleMaterialSink(trace, ShaderTree::SinkSpecular);
|
||||
self = SampleMaterialSink(trace, ShaderTree::SinkConstant);
|
||||
}
|
||||
|
||||
// Final color.
|
||||
o = ((diffuse * (l_diff + l_indirect + ambient* ambient_occlusion)) + specular * l_spec + self) /** alpha*/; // Don't multiply the alpha, because there is real raytracing for the refraction after.
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = 0;
|
||||
o.Set(0, 0, 0);
|
||||
}
|
||||
|
||||
// Apply fog.
|
||||
if (scene->fog_far > 0)
|
||||
{
|
||||
float kfog = Types::Clamp((trace.td - scene->fog_near) / (scene->fog_far - scene->fog_near));
|
||||
o = o * (1.f - kfog) + scene->fog_color * kfog;
|
||||
}
|
||||
|
||||
// Trace reflected and transmitted rays as required.
|
||||
float krefl = alpha;
|
||||
|
||||
float eta = trace.m->irefraction;
|
||||
if (trace.ir == trace.m->irefraction)
|
||||
eta = 1.0f;
|
||||
|
||||
if (((alpha < 1) || blend_additive) && bounce.refraction)
|
||||
{
|
||||
float n = trace.ir / eta;
|
||||
|
||||
if (configuration.fresnel_activate)
|
||||
krefl = Fresnel(trace.d, trace.n.FaceForward(trace.d), n);
|
||||
|
||||
float c1 = -trace.n.FaceForward(trace.d).Dot(trace.d);
|
||||
float w = n * Types::Abs(c1);
|
||||
float c2 = Math::Sqrt(1 + (w - n) * (w + n));
|
||||
|
||||
Vector4 rtransmit = (trace.d * n) + trace.n.FaceForward(trace.d) * (w - c2);
|
||||
rtransmit = rtransmit.Normalized();
|
||||
Vector4 offset_pi = trace.pi + rtransmit * Units::Mm(1.f);
|
||||
|
||||
if (c2 < 0)
|
||||
krefl = 1.0f; // Full reflection, we are inside the matter and by an angle where it is physically impossible (as Snell-Descartes law) to have refraction.
|
||||
|
||||
if ((1.0f - krefl) > 0.0f)
|
||||
{
|
||||
bounce.refraction--;
|
||||
|
||||
Color b;
|
||||
float save_ir = trace.ir;
|
||||
trace.ir = eta;
|
||||
Raytrace(RayGrid(offset_pi, rtransmit), b, bounce, &trace);
|
||||
trace.ir = save_ir;
|
||||
|
||||
if (blend_additive)
|
||||
o += b;
|
||||
else o = o * krefl + b * (1 - krefl);
|
||||
|
||||
bounce.refraction++;
|
||||
}
|
||||
}
|
||||
|
||||
// Reflection.
|
||||
float material_reflection = SampleMaterialSink(trace, ShaderTree::SinkReflection).x;
|
||||
if (configuration.trace_reflection && material_reflection && bounce.reflection)
|
||||
{
|
||||
if (krefl > 0.0f)
|
||||
{
|
||||
bounce.reflection--;
|
||||
|
||||
Vector4 nf = trace.n.FaceForward(trace.d).Normalized();
|
||||
float c1 = -nf.Dot(trace.d);
|
||||
Vector4 rreflect = trace.d + (nf * 2.f * Types::Abs(c1));
|
||||
|
||||
Vector4 offset_pi = trace.pi + rreflect * Units::Mm(1.f) ;
|
||||
|
||||
Color b;
|
||||
float save_ir = trace.ir;
|
||||
trace.ir = eta;
|
||||
Raytrace(RayGrid(offset_pi, rreflect), b, bounce, &trace);
|
||||
trace.ir = save_ir;
|
||||
|
||||
o += b * (krefl * material_reflection);
|
||||
|
||||
bounce.reflection++;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: Isn't doing this here getting rid of HDR informations?
|
||||
o = o.Clamped(Vector4(0, 0, 0), Vector4(1, 1, 1));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Raytracer::PrimaryRay(const RayGrid &ray, Color &o)
|
||||
{
|
||||
Bounce bounce;
|
||||
bounce.indirect = configuration.indirect_gi_bounce;
|
||||
bounce.reflection = configuration.trace_reflection_max_recursion;
|
||||
bounce.refraction = configuration.trace_refraction_max_recursion;
|
||||
Raytrace(ray, o, bounce);
|
||||
}
|
||||
void Raytracer::Raytrace(const RayGrid &ray, Color &o, Bounce &bounce, Trace *previous_trace)
|
||||
{
|
||||
Trace trace;
|
||||
|
||||
if (previous_trace)
|
||||
{
|
||||
trace.ir = previous_trace->ir;
|
||||
trace.td = previous_trace->td;
|
||||
}
|
||||
|
||||
scene_tree.RaytraceScene(trace, ray.p[0], ray.d[0]);
|
||||
statistics.ray_count++;
|
||||
statistics.tri_test += trace.tri_test;
|
||||
|
||||
// Shade result.
|
||||
if (trace.has_i)
|
||||
{
|
||||
// Compute intersection point.
|
||||
trace.pi = trace.s + trace.d * trace.i_t;
|
||||
|
||||
// Compute intersection normal.
|
||||
Vector4 normal_sink = SampleMaterialSink(trace, ShaderTree::SinkNormal);
|
||||
trace.o->GetMatrix().ApplyRotation(&trace.n, &normal_sink);
|
||||
trace.n.Normalize();
|
||||
if (trace.backface)
|
||||
trace.n = trace.n.Reversed();
|
||||
|
||||
// Integrate the newly traveled distance.
|
||||
trace.td += trace.i_t;
|
||||
|
||||
// Gather radiance.
|
||||
ComputeRadiance(trace, o, bounce);
|
||||
}
|
||||
else
|
||||
o = scene->background_color;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Raytracer::Render(Picture &output, uint w, uint h)
|
||||
{
|
||||
if (!w || !h)
|
||||
return false;
|
||||
|
||||
uint logical_h = h;
|
||||
viewport.Set((float)w, (float)h);
|
||||
|
||||
if (configuration.interlaced)
|
||||
{
|
||||
if (h & 1)
|
||||
__ERR__(__LOG_E__ << "Interlaced frame height must be a multiple of 2.", false)
|
||||
if (configuration.interlaced_trace_half_frame)
|
||||
h /= 2;
|
||||
}
|
||||
|
||||
Camera *camera = scene->current_camera;
|
||||
if (!camera)
|
||||
return false;
|
||||
|
||||
// Create destination picture.
|
||||
output.AllocAs(w, h);
|
||||
|
||||
// Allocate output hdr buffer.
|
||||
Array <Color> hdr(w * h);
|
||||
if (!hdr)
|
||||
__ERR__(__LOG_E__<< "Failed to allocate floating point frame buffer.\n", false)
|
||||
|
||||
// Reset statistics.
|
||||
render_clock = scene->GetClock()->Getf();
|
||||
statistics.Reset();
|
||||
|
||||
// Progress structure.
|
||||
Progress progress;
|
||||
|
||||
progress.start_clock = Platform::Get().GetClock();
|
||||
progress.instance = this;
|
||||
progress.progress = 0;
|
||||
progress.buffer = hdr;
|
||||
progress.w = 0;
|
||||
progress.h = 0;
|
||||
progress.done = false;
|
||||
|
||||
// Create virtual screen.
|
||||
Benchmark bench(true);
|
||||
scene_tree.ResetStats();
|
||||
|
||||
Vector4 screen[4], wscreen[4];
|
||||
|
||||
float hw, hh, ar = ((camera->aspect_ratio == -1.f) ? 1.f : camera->aspect_ratio);
|
||||
|
||||
if (camera->aspect_ratio_ref_yaxis)
|
||||
{
|
||||
hw = ((float)w / (float)logical_h) / ar;
|
||||
hh = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
hw = 1;
|
||||
hh = ((float)logical_h / ar) / (float)w;
|
||||
}
|
||||
|
||||
screen[0].Set(-hw, hh, camera->zoom_factor);
|
||||
screen[1].Set(hw, hh, camera->zoom_factor);
|
||||
screen[2].Set(hw, -hh, camera->zoom_factor);
|
||||
screen[3].Set(-hw, -hh, camera->zoom_factor);
|
||||
|
||||
camera->GetMatrix().Apply(wscreen, screen, 4);
|
||||
|
||||
// Interpolate across world screen and trace.
|
||||
Vector4 dt_l, pt_l, dt_r, pt_r;
|
||||
|
||||
dt_l = (wscreen[3] - wscreen[0]) / (float)logical_h;
|
||||
pt_l = wscreen[0];
|
||||
dt_r = (wscreen[2] - wscreen[1]) / (float)logical_h;
|
||||
pt_r = wscreen[1];
|
||||
|
||||
// Interlace.
|
||||
if (configuration.interlaced && configuration.interlaced_trace_half_frame)
|
||||
{
|
||||
if (!interlace_even)
|
||||
{
|
||||
pt_l += dt_l;
|
||||
pt_r += dt_r;
|
||||
}
|
||||
dt_l *= 2.f;
|
||||
dt_r *= 2.f;
|
||||
}
|
||||
|
||||
const Vector4 &s = camera->GetMatrix().GetRow(3);
|
||||
|
||||
// Rendering.
|
||||
abort = false;
|
||||
progress.description = "Rendering (1/2)";
|
||||
|
||||
#define __JobTileSize 32
|
||||
|
||||
// Split rendering in tiles.
|
||||
AutoList <ASync::Job *> job_list;
|
||||
ASync::JobGroup group;
|
||||
|
||||
for (uint y = 0; y < h; y += __JobTileSize)
|
||||
for (uint x = 0; x < w; x += __JobTileSize)
|
||||
{
|
||||
RaytraceJob *job = new RaytraceJob;
|
||||
job_list.Add(job);
|
||||
|
||||
job->core = this;
|
||||
|
||||
job->start_height = y;
|
||||
job->end_height = y + __JobTileSize < h ? y + __JobTileSize : h;
|
||||
job->start_width = x;
|
||||
job->end_width = x + __JobTileSize < w ? x + __JobTileSize : w;
|
||||
|
||||
job->s = s;
|
||||
job->dt_l = dt_l; job->pt_l = pt_l;
|
||||
job->dt_r = dt_r; job->pt_r = pt_r;
|
||||
|
||||
job->hdr = hdr;
|
||||
job->pitch = w;
|
||||
|
||||
Platform::Get().job_manager->EnqueueJob(job, &group);
|
||||
}
|
||||
|
||||
while (!Platform::Get().job_manager->JoinGroup(&group, false))
|
||||
if (hook)
|
||||
{
|
||||
// progress.progress = 1.f - (float)group.GetJobCount() / job_list.GetCount();
|
||||
hook->RaytracerProgress(progress);
|
||||
}
|
||||
|
||||
job_list.Clear();
|
||||
/*
|
||||
// Split anti-aliasing in tiles.
|
||||
progress.description = "Anti-aliasing (2/2)";
|
||||
|
||||
for (uint y = 1; y < (h - 1); y += __JobTileSize)
|
||||
for (uint x = 1; x < (w - 1); x += __JobTileSize)
|
||||
{
|
||||
nAntialiasJob *job = new nAntialiasJob;
|
||||
job_list.Add(job);
|
||||
|
||||
job->core = this;
|
||||
|
||||
job->start_height = y;
|
||||
job->end_height = y + __JobTileSize < (h - 1) ? y + __JobTileSize : (h - 1);
|
||||
job->start_width = x;
|
||||
job->end_width = x + __JobTileSize < (w - 1) ? x + __JobTileSize : (w - 1);
|
||||
|
||||
job->s = s;
|
||||
job->dt_l = dt_l; job->pt_l = pt_l;
|
||||
job->dt_r = dt_r; job->pt_r = pt_r;
|
||||
|
||||
job->hdr = hdr;
|
||||
job->pitch = w;
|
||||
|
||||
Platform::Get().job_manager->EnqueueJob(job, &group);
|
||||
}
|
||||
|
||||
// Join anti-aliasing job group.
|
||||
while (!Platform::Get().job_manager->JoinGroup(&group, false))
|
||||
if (hook)
|
||||
{
|
||||
// progress.progress = 1.f - (float)group.GetJobCount() / job_list.GetCount();
|
||||
hook->RaytracerProgress(progress);
|
||||
}
|
||||
|
||||
job_list.Clear();
|
||||
*/
|
||||
bench.Stop();
|
||||
__LOG__ << "Raytracing done. Took " << bench.GetMs() << " ms. Ray/s = " << (scene_tree.ray_count * 1000) / bench.GetMs() << "\n";
|
||||
|
||||
// HDR conversion to standard 32 bit RGBA.
|
||||
#pragma omp parallel
|
||||
{
|
||||
#pragma omp for schedule(dynamic) nowait
|
||||
for (uint v = 0; v < h; ++v)
|
||||
{
|
||||
uint *o_rgb = ((uint *)output.GetData()) + w * v;
|
||||
Color *o_hdr = hdr + w * v;
|
||||
|
||||
for (uint u = 0; u < w; ++u)
|
||||
o_rgb[u] =
|
||||
((uint)(Types::Clamp(o_hdr[u].w) * 255) << 24) +
|
||||
((uint)(Types::Clamp(o_hdr[u].x) * 255) << 16) +
|
||||
((uint)(Types::Clamp(o_hdr[u].y) * 255) << 8) +
|
||||
((uint)(Types::Clamp(o_hdr[u].z) * 255));
|
||||
}
|
||||
}
|
||||
// ...
|
||||
|
||||
// Backup current frame if interlaced and wait for the next half-frame.
|
||||
if (configuration.interlaced)
|
||||
{
|
||||
if (interlace_half_frame.isValid())
|
||||
{
|
||||
// If the frame is valid compose to output.
|
||||
if ((interlace_half_frame.GetWidth() != w) || (interlace_half_frame.GetHeight() != h))
|
||||
__LOG_E__ << "Unexpected frame dimension change during interlaced sequence rendering.\n";
|
||||
|
||||
else
|
||||
{
|
||||
Picture half_frame(output);
|
||||
|
||||
if (output.AllocAs(w, logical_h))
|
||||
{
|
||||
// Select even and odd frames based on current parity.
|
||||
Picture *even = interlace_even ? &half_frame : &interlace_half_frame,
|
||||
*odd = interlace_even ? &interlace_half_frame : &half_frame;
|
||||
|
||||
// Compose.
|
||||
uint *p_even = (uint *)even->GetData(),
|
||||
*p_odd = (uint *)odd->GetData(),
|
||||
*p_output = (uint *)output.GetData();
|
||||
|
||||
if (configuration.interlaced_trace_half_frame)
|
||||
for (uint v = 0; v < h; ++v)
|
||||
{
|
||||
Memory::Copy(p_output, p_even, w * 4);
|
||||
p_even += w;
|
||||
p_output += w;
|
||||
|
||||
Memory::Copy(p_output, p_odd, w * 4);
|
||||
p_odd += w;
|
||||
p_output += w;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (interlace_even)
|
||||
p_even += w;
|
||||
else p_odd += w;
|
||||
|
||||
for (uint v = 0; v < h; ++v)
|
||||
{
|
||||
Memory::Copy(p_output, p_even, w * 4);
|
||||
p_even += w * 2;
|
||||
p_output += w;
|
||||
|
||||
Memory::Copy(p_output, p_odd, w * 4);
|
||||
p_odd += w * 2;
|
||||
p_output += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Drop buffer, it has been committed to output.
|
||||
interlace_half_frame.Free();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Buffer the current output and drop it. No save is to be done yet.
|
||||
interlace_half_frame.Clone(output);
|
||||
output.Free();
|
||||
}
|
||||
}
|
||||
|
||||
// Done, switch interlace parity.
|
||||
interlace_even = !interlace_even;
|
||||
viewport.Set(1, 1);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Raytracer::StartInterlacedSequence()
|
||||
{
|
||||
interlace_even = configuration.interlace_even;
|
||||
interlace_half_frame.Free();
|
||||
}
|
||||
void Raytracer::Abort()
|
||||
{ abort = true; }
|
||||
void Raytracer::SetConfiguration(const Configuration &config)
|
||||
{
|
||||
configuration = config;
|
||||
for (int n = 0; n < 32; ++n)
|
||||
monte_carlo[n].Initialize(configuration.gi_sample, configuration.gi_sample, Units::Deg(configuration.ao_angle)); // 64 evaluations per ray.
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Raytracer::SetScene(const GS::S3D::Scene *s)
|
||||
{
|
||||
if (!gf)
|
||||
__ERR__(__LOG_E__ << "No graphic resource factory to set raytracer scene.\n", false)
|
||||
|
||||
Free();
|
||||
|
||||
// Grab scene and shadow scene.
|
||||
scene = s;
|
||||
if (!scene_tree.SetScene(*gf, s) || !scene_shadow_tree.SetScene(*gf, s, true))
|
||||
return false;
|
||||
|
||||
// Grab lights, reset caches.
|
||||
SharedList <S3D::MLight *> lights;
|
||||
s->GetItemListByType(lights);
|
||||
|
||||
if (!lgt.Allocate(lights.GetCount()))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate raytracer light array.\n", false)
|
||||
|
||||
uint lgt_count = 0;
|
||||
ListForeachPtr(S3D::MLight *, l, lights)
|
||||
{
|
||||
lgt[lgt_count].l = l->isActive() ? l : NULL;
|
||||
lgt[lgt_count].g = NULL;
|
||||
lgt_count++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void Raytracer::Free()
|
||||
{
|
||||
scene_tree.Free();
|
||||
scene_shadow_tree.Free();
|
||||
|
||||
lgt.Free();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Raytracer::Raytracer(ResourceFactory *f) : gf(f)
|
||||
{
|
||||
SetConfiguration(configuration);
|
||||
viewport.Set(1, 1);
|
||||
hook = NULL;
|
||||
}
|
||||
89
include/modules/raytracer/raytracer_geometry.cpp
Normal file
89
include/modules/raytracer/raytracer_geometry.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "raytracer/raytracer_core.h"
|
||||
#include "core/geometry.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::Raytrace;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Vector4 Raytracer::SampleGeometryAttribute(const Trace &trace, GeometryAttribute attr)
|
||||
{
|
||||
Vector4 sample;
|
||||
|
||||
switch (attr)
|
||||
{
|
||||
case GeometryVertexColor:
|
||||
if (trace.g->rgb)
|
||||
sample = ( trace.g->rgb[trace.bi + 0] * trace.w +
|
||||
trace.g->rgb[trace.bi + trace.it + 1] * trace.u +
|
||||
trace.g->rgb[trace.bi + trace.it + 2] * trace.v );
|
||||
else
|
||||
sample.Set(0.25f, 0.f, 0.f);
|
||||
break;
|
||||
|
||||
case GeometryNormal:
|
||||
{
|
||||
if (
|
||||
(trace.m->renderword & Material::Render_Smooth) ||
|
||||
(trace.m->renderword & Material::Render_NormalTangent)
|
||||
)
|
||||
{
|
||||
// Interpolated vertex normal.
|
||||
sample = ( trace.g->vtx_normal[trace.bi + 0] * trace.w +
|
||||
trace.g->vtx_normal[trace.bi + trace.it + 1] * trace.u +
|
||||
trace.g->vtx_normal[trace.bi + trace.it + 2] * trace.v ).Normalized();
|
||||
|
||||
// Normal map support.
|
||||
if (trace.m->GetChannelStage(Channel_Normal))
|
||||
{
|
||||
if (trace.m->renderword & Material::Render_NormalTangent)
|
||||
{
|
||||
Vector4 T, B;
|
||||
|
||||
if (trace.g->vtx_tangent)
|
||||
{
|
||||
// Interpolated tangent basis.
|
||||
T = ( trace.g->vtx_tangent[trace.bi + 0].T * trace.w +
|
||||
trace.g->vtx_tangent[trace.bi + trace.it + 1].T * trace.u +
|
||||
trace.g->vtx_tangent[trace.bi + trace.it + 2].T * trace.v ).Normalized();
|
||||
B = ( trace.g->vtx_tangent[trace.bi + 0].B * trace.w +
|
||||
trace.g->vtx_tangent[trace.bi + trace.it + 1].B * trace.u +
|
||||
trace.g->vtx_tangent[trace.bi + trace.it + 2].B * trace.v ).Normalized();
|
||||
}
|
||||
else
|
||||
{
|
||||
T.Set(1, 0, 0);
|
||||
B.Set(0, 1, 0);
|
||||
}
|
||||
|
||||
// Build tangent frame.
|
||||
Matrix3 tangent_matrix(T, B, sample);
|
||||
Vector4 normal_sample(SampleMaterialAttribute(trace, Channel_Normal)),
|
||||
tangent_normal(normal_sample.x * 2 - 1, normal_sample.y * 2 - 1, normal_sample.z * 2 - 1);
|
||||
|
||||
sample = tangent_normal * tangent_matrix;
|
||||
}
|
||||
else
|
||||
{
|
||||
// World space.
|
||||
Vector4 normal_sample(SampleMaterialAttribute(trace, Channel_Normal)),
|
||||
tangent_normal(normal_sample.x * 2 - 1, normal_sample.z * 2 - 1, normal_sample.y * 2 - 1);
|
||||
sample = tangent_normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
sample = trace.g->pol_normal[trace.ip];
|
||||
}
|
||||
break;
|
||||
}
|
||||
return sample;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
79
include/modules/raytracer/raytracer_job.cpp
Normal file
79
include/modules/raytracer/raytracer_job.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "raytracer/raytracer_job.h"
|
||||
#include "core/geometry.h"
|
||||
#include "rand/rand.h"
|
||||
|
||||
using namespace GS::Raytrace;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RaytraceJob::Execute(uint)
|
||||
{
|
||||
Vector4 pt_s = pt_l + dt_l * (float)start_height;
|
||||
|
||||
for (int v = start_height; v < end_height; ++v)
|
||||
{
|
||||
Vector4 dt_s = ((pt_r + dt_r * (float)start_height) - (pt_l + dt_l * (float)start_height)) / (float)pitch;
|
||||
for (int u = start_width; u < end_width; ++u)
|
||||
{
|
||||
Vector4 d = (pt_s + dt_s * (float)u - s).Normalized();
|
||||
core->PrimaryRay(RayGrid(s, d), hdr[v * pitch + u]);
|
||||
}
|
||||
pt_s += dt_l;
|
||||
}
|
||||
}
|
||||
void AntialiasJob::Execute(uint)
|
||||
{
|
||||
Configuration &config = core->GetConfiguration();
|
||||
|
||||
float aa_v_k = config.interlaced_trace_half_frame ? 0.5f : 1.f,
|
||||
aa_threshold = config.aa_threshold,
|
||||
aa_jitter = config.aa_jitter;
|
||||
|
||||
int aa_sample = config.aa_sample;
|
||||
|
||||
// When rendering half frame halve the AA kernel vertically.
|
||||
for (int v = start_height; v < end_height; ++v)
|
||||
for (int u = start_width; u < end_width; ++u)
|
||||
{
|
||||
Color *o_hdr = &hdr[v * pitch + u];
|
||||
|
||||
// Check threshold.
|
||||
if (
|
||||
(Vector4::Dist2(o_hdr[0], o_hdr[-1]) < aa_threshold) &&
|
||||
(Vector4::Dist2(o_hdr[0], o_hdr[-pitch]) < aa_threshold) &&
|
||||
(Vector4::Dist2(o_hdr[0], o_hdr[1]) < aa_threshold) &&
|
||||
(Vector4::Dist2(o_hdr[0], o_hdr[pitch]) < aa_threshold)
|
||||
)
|
||||
continue;
|
||||
|
||||
// Multi-sample.
|
||||
o_hdr[0].Set(0, 0, 0);
|
||||
|
||||
for (int ms_v = 0; ms_v < aa_sample; ++ms_v)
|
||||
{
|
||||
// TODO pre-calculate jittered/non-jittered grids.
|
||||
float ms_v_o = v + ((float)ms_v * aa_v_k) / aa_sample + (aa_jitter ? Random::FRand(0.125f / aa_sample) : 0);
|
||||
|
||||
Vector4 dt_s = ((pt_r + dt_r * ms_v_o) - (pt_l + dt_l * ms_v_o)) / (float)pitch,
|
||||
pt_s = pt_l + dt_l * ms_v_o;
|
||||
|
||||
for (int ms_u = 0; ms_u < aa_sample; ++ms_u)
|
||||
{
|
||||
float ms_u_o = u + (float)ms_u / aa_sample + (aa_jitter ? Random::FRand(0.125f / aa_sample) : 0);
|
||||
Vector4 d = (pt_s + dt_s * ms_u_o - s).Normalized();
|
||||
|
||||
Color out;
|
||||
core->PrimaryRay(RayGrid(s, d), out);
|
||||
o_hdr[0] += out.Clamped(0, 1);
|
||||
}
|
||||
}
|
||||
o_hdr[0] /= (float)(aa_sample * aa_sample);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
181
include/modules/raytracer/raytracer_material.cpp
Normal file
181
include/modules/raytracer/raytracer_material.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include "raytracer/raytracer_core.h"
|
||||
#include "core/camera.h"
|
||||
#include "core/geometry.h"
|
||||
#include "core/shader_block.h"
|
||||
#include "scene3d/scene.h"
|
||||
|
||||
using namespace GS::Core;
|
||||
using namespace GS::Raytrace;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
GS::Vector4 Raytracer::SampleMaterialSink(const Trace &trace, ShaderTree::ShaderSinkType sink)
|
||||
{
|
||||
if (trace.st)
|
||||
{
|
||||
// Evaluate sink.
|
||||
if (ShaderBlock *block = trace.st->sink[sink])
|
||||
{
|
||||
ShaderBlockValue block_out;
|
||||
if (EvaluateShaderBlock(trace, block, block_out))
|
||||
return block_out.v;
|
||||
}
|
||||
|
||||
// Default values.
|
||||
switch (sink)
|
||||
{
|
||||
case ShaderTree::SinkNormal: return Vector4(0, 0, 1);
|
||||
case ShaderTree::SinkDiffuse: return trace.m->diffuse;
|
||||
case ShaderTree::SinkModulate: return Vector4(1, 1, 1);
|
||||
case ShaderTree::SinkSpecular: return trace.m->specular;
|
||||
case ShaderTree::SinkGlossiness: return Vector4(trace.m->glossiness, 0, 0);
|
||||
case ShaderTree::SinkConstant: return Vector4(0, 0, 0);
|
||||
case ShaderTree::SinkOpacity: return Vector4(1, 0, 0);
|
||||
case ShaderTree::SinkReflection: return Vector4(trace.m->reflection, 0, 0);
|
||||
}
|
||||
}
|
||||
return Vector4(1, 0, 0, 1);
|
||||
}
|
||||
GS::Vector4 Raytracer::SampleMaterialAttribute(const Trace &trace, MaterialChannel channel)
|
||||
{
|
||||
Color sample(1, 1, 1);
|
||||
if (!trace.m)
|
||||
return sample;
|
||||
|
||||
Material::TextureStage *stage = trace.m->GetChannelStage(channel);
|
||||
|
||||
/*
|
||||
Texture sampling.
|
||||
@TODO This is insanely slow.
|
||||
*/
|
||||
if (stage && trace.g)
|
||||
{
|
||||
float sample_uv_u = 0, sample_uv_v = 0;
|
||||
|
||||
switch (stage->uv_mode)
|
||||
{
|
||||
case Material::UV_SphericalEnvironment:
|
||||
{
|
||||
Vector4 w;
|
||||
scene->current_camera->GetInverseMatrix().ApplyRotation(&w, &trace.n);
|
||||
|
||||
// Find the Euler vector from the reflection normal.
|
||||
Vector4 euler_vec = trace.d - (w * 2.0f * fabs((w*-1.0f).Dot(trace.d)));
|
||||
euler_vec.Normalize();
|
||||
|
||||
// Euler to UV coordinate.
|
||||
// float Y = (1.0f - euler_vec.y) * 0.5f;
|
||||
|
||||
Vector4 XZ(euler_vec.x, euler_vec.z, 0.0);
|
||||
XZ.Normalize();
|
||||
float DotX = /*nVector(1.0f, 0.0f, 0.0f).Dot(XZ)*/XZ.x;
|
||||
|
||||
// Set from -1;1 to 0;1.
|
||||
DotX = (1.0f - DotX) * 0.5f;
|
||||
|
||||
float DotY = /*nVector(0.0f, 1.0f, 0.0f).Dot(XZ)*/XZ.y;
|
||||
// Set -1 or 1.
|
||||
DotY = (DotY >= 0 ? 1.0f :-1.0f);
|
||||
|
||||
float value_angle = DotX * DotY;
|
||||
// Set from -1;1 to 0;1.
|
||||
value_angle = (1.0f - value_angle) * 0.5f;
|
||||
|
||||
sample_uv_u = DotX;
|
||||
sample_uv_v = value_angle;
|
||||
}
|
||||
break;
|
||||
|
||||
case Material::UV_LSN:
|
||||
{
|
||||
// Derive UV coordinates from intersection normal.
|
||||
Vector4 w;
|
||||
scene->current_camera->GetInverseMatrix().ApplyRotation(&w, &trace.n);
|
||||
|
||||
sample_uv_u = w.x * 0.5f + 0.5f;
|
||||
sample_uv_v = w.y * 0.5f + 0.5f;
|
||||
}
|
||||
break;
|
||||
|
||||
case Material::UV_FrontMap:
|
||||
{
|
||||
// Derive UV coordinated from view item projection matrix.
|
||||
Vector4 s;
|
||||
scene->current_camera->WorldToScreen(fRect(0, 0, viewport.x, viewport.y), trace.pi, s, false);
|
||||
|
||||
float k_ar = viewport.y / viewport.x;
|
||||
sample_uv_u = (s.x - 0.5f) * k_ar + 0.5f;
|
||||
sample_uv_v = s.y;
|
||||
}
|
||||
break;
|
||||
|
||||
case Material::UV_UV:
|
||||
// Compute UV from geometry topology.
|
||||
if (Vector2 *uv = (stage->uv_index < __UV_PER_GEOMETRY__) ? &trace.g->uv[stage->uv_index][0] : NULL)
|
||||
{
|
||||
Vector2 &uv0 = uv[trace.bi], &uv1 = uv[trace.bi + trace.it + 1], &uv2 = uv[trace.bi + trace.it + 2];
|
||||
sample_uv_u = trace.w * uv0.x + trace.u * uv1.x + trace.v * uv2.x,
|
||||
sample_uv_v = trace.w * uv0.y + trace.u * uv1.y + trace.v * uv2.y;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// UV matrix.
|
||||
Vector4 sample_uv = Vector4(sample_uv_u, sample_uv_v, 0.0) * stage->uv_matrix;
|
||||
|
||||
// Handle wrapping.
|
||||
/*
|
||||
if (stage->wrap_u)
|
||||
{
|
||||
if (sample_uv.x < 0)
|
||||
sample_uv.x = sample_uv.x - (int)sample_uv.x + 1;
|
||||
else sample_uv.x = sample_uv.x - (int)sample_uv.x;
|
||||
}
|
||||
if (stage->wrap_v)
|
||||
{
|
||||
if (sample_uv.y < 0)
|
||||
sample_uv.y = sample_uv.y - (int)sample_uv.y + 1;
|
||||
else sample_uv.y = sample_uv.y - (int)sample_uv.y;
|
||||
}
|
||||
*/
|
||||
// FIXME performance bottleneck!
|
||||
if (Picture *p = gf->LoadPicture(stage->t))
|
||||
p->SampleRGBA(sample_uv.x, sample_uv.y, sample);
|
||||
}
|
||||
else
|
||||
switch (channel)
|
||||
{
|
||||
case Channel_Diffuse:
|
||||
sample *= trace.m->diffuse;
|
||||
break;
|
||||
case Channel_Specular:
|
||||
sample *= trace.m->specular;
|
||||
break;
|
||||
case Channel_SelfIllum:
|
||||
sample *= trace.m->self;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
return sample;
|
||||
}
|
||||
float Raytracer::SampleMaterialOpacity(const Trace &trace)
|
||||
{
|
||||
float opacity = 1.f;
|
||||
|
||||
if (trace.m->GetChannelStage(Channel_Opacity))
|
||||
{
|
||||
Vector4 sample = SampleMaterialAttribute(trace, Channel_Opacity);
|
||||
opacity = sample.w;
|
||||
}
|
||||
return opacity * trace.m->opacity;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
275
include/modules/raytracer/raytracer_scene.cpp
Normal file
275
include/modules/raytracer/raytracer_scene.cpp
Normal file
@ -0,0 +1,275 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "raytracer/raytracer_scene.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/instance.h"
|
||||
#include "scene3d/group.h"
|
||||
#include "core/geometry_bih.h"
|
||||
#include "metafile/nml_object.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::Raytrace;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void SceneBIH::ResetStats()
|
||||
{
|
||||
ray_count = 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void SceneBIH::TraceLeaf(BIH::Node *leaf, float tmin, float tmax, BIH::Trace &trace, void *parm)
|
||||
{
|
||||
Vector4 &s = trace.s, &d = trace.d;
|
||||
Trace *s_trace = (Trace *)parm;
|
||||
uint *leaf_indice = (uint *)leaf->p;
|
||||
|
||||
for (uint n = 0; n < leaf->count; ++n)
|
||||
{
|
||||
Core::Object *o = obj[leaf_indice[n]].o;
|
||||
IGeometryTree *tree = obj[leaf_indice[n]].tree;
|
||||
|
||||
// Raytrace object in local space.
|
||||
Vector4 local_s = s * o->GetInverseMatrix(), local_d;
|
||||
o->GetInverseMatrix().ApplyRotation(&local_d, &d);
|
||||
|
||||
GeometryTrace geo_trace;
|
||||
tree->RaytraceGeometry(geo_trace, local_s, local_d, tmax);
|
||||
|
||||
if (!geo_trace.has_i)
|
||||
continue;
|
||||
|
||||
// Integrate result.
|
||||
if (!s_trace->has_i || (geo_trace.i_t < s_trace->i_t))
|
||||
{
|
||||
/*
|
||||
Note: Do not copy the complete geo_trace, we do not want
|
||||
to duplicate trace stacks.
|
||||
*/
|
||||
*((GeometryTraceBase *)s_trace) = ((GeometryTraceBase &)geo_trace);
|
||||
|
||||
s_trace->has_i = true;
|
||||
|
||||
s_trace->o = o;
|
||||
s_trace->tri_test += geo_trace.tri_test;
|
||||
}
|
||||
}
|
||||
}
|
||||
void SceneBIH::RaytraceScene(Trace &trace, const Vector4 &s, const Vector4 &d, float l)
|
||||
{
|
||||
ray_count++;
|
||||
|
||||
trace.s = s;
|
||||
trace.d = d;
|
||||
|
||||
BIH::Trace bih_trace;
|
||||
Tree::Raytrace(bih_trace, s, d, l, (void *)&trace);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Geometry *SceneBIH::TranslateGeometry(Geometry *g) const
|
||||
{
|
||||
if (obj && g)
|
||||
for (uint n = 0; n < obj.GetCount(); ++n)
|
||||
if (obj[n].g == g)
|
||||
return obj[n].og;
|
||||
return g;
|
||||
}
|
||||
void SceneBIH::AddObject(ResourceFactory &gf, S3D::MObject *o, uint &obj_count, MinMax *varray, bool shadow)
|
||||
{
|
||||
if (!o->isActive())
|
||||
return;
|
||||
if (o->geometry.IsEmpty() || !o->GetBaseItem()->opacity)
|
||||
return;
|
||||
if (o->mitem_flags.IsSet(S3D::MItem::Flag_IsHelper | S3D::MItem::Flag_EditorHidden | S3D::MItem::Flag_EditorLocked))
|
||||
return;
|
||||
|
||||
// Grab object geometry.
|
||||
Geometry *g = gf.LoadGeometry(o->geometry);
|
||||
if (!g)
|
||||
return;
|
||||
|
||||
obj[obj_count].og = g; // Store original geometry to map back from skinned geometry.
|
||||
if (!g->material_table.GetCount() || !g->pol.GetCount())
|
||||
return;
|
||||
|
||||
if (shadow)
|
||||
{
|
||||
if (g->flag.IsSet(Geometry::FlagNullShadowProxy))
|
||||
return;
|
||||
if (!g->shadow_proxy.IsEmpty())
|
||||
g = gf.LoadGeometry(g->shadow_proxy);
|
||||
}
|
||||
|
||||
// Perform skinning.
|
||||
if (o->HasSkin() && g->skin)
|
||||
{
|
||||
Skin *skin = o->GetSkin();
|
||||
|
||||
// Serialize geometry.
|
||||
using namespace NML;
|
||||
|
||||
File file;
|
||||
file.AddRoot(g->AsMetaTag());
|
||||
|
||||
Geometry *sg = new Geometry;
|
||||
LoadFromFile(*sg, file);
|
||||
|
||||
// Build required structures upfront.
|
||||
sg->ComputeVertexNormal();
|
||||
sg->ComputeVertexTangent();
|
||||
|
||||
// Vertex skinning.
|
||||
for (uint n = 0; n < sg->vtx.GetCount(); ++n)
|
||||
{
|
||||
Vector4 v(0, 0, 0);
|
||||
for (int b = 0; b < 4; ++b)
|
||||
{
|
||||
if (!sg->skin[n].w[b])
|
||||
break;
|
||||
v += (sg->vtx[n] * skin->bones_mtx[sg->skin[n].bone_index[b]]) * sg->skin[n].w[b];
|
||||
}
|
||||
sg->vtx[n] = v;
|
||||
}
|
||||
|
||||
// Normal skinning.
|
||||
Vector4 s, w;
|
||||
int tt = 0;
|
||||
for (uint p = 0; p < sg->pol.GetCount(); ++p)
|
||||
for (uint n = 0; n < sg->pol[p].vtx_count; ++n)
|
||||
{
|
||||
s.Set(0, 0, 0);
|
||||
for (int b = 0; b < 4; ++b)
|
||||
{
|
||||
int i = sg->pol[p].binding[n];
|
||||
if (!sg->skin[i].w[b])
|
||||
break;
|
||||
skin->bones_mtx[sg->skin[i].bone_index[b]].ApplyRotation(&w, &sg->vtx_normal[tt]);
|
||||
s += w * sg->skin[i].w[b];
|
||||
}
|
||||
sg->vtx_normal[tt++] = s;
|
||||
}
|
||||
|
||||
// Tangent base skinning.
|
||||
Vector4 _b, _t;
|
||||
tt = 0;
|
||||
for (uint p = 0; p < sg->pol.GetCount(); ++p)
|
||||
for (uint n = 0; n < sg->pol[p].vtx_count; ++n)
|
||||
{
|
||||
_b.Set(0, 0, 0);
|
||||
_t.Set(0, 0, 0);
|
||||
for (int b = 0; b < 4; ++b)
|
||||
{
|
||||
int i = sg->pol[p].binding[n];
|
||||
if (!sg->skin[i].w[b])
|
||||
break;
|
||||
|
||||
skin->bones_mtx[sg->skin[i].bone_index[b]].ApplyRotation(&w, &sg->vtx_tangent[tt].B);
|
||||
_b += w * sg->skin[i].w[b];
|
||||
skin->bones_mtx[sg->skin[i].bone_index[b]].ApplyRotation(&w, &sg->vtx_tangent[tt].T);
|
||||
_t += w * sg->skin[i].w[b];
|
||||
}
|
||||
sg->vtx_tangent[tt].B = _b;
|
||||
sg->vtx_tangent[tt].T = _t;
|
||||
tt++;
|
||||
}
|
||||
|
||||
// Use as the base geometry.
|
||||
// but first copy the material from the base material
|
||||
sg->material_table.Allocate(g->material_table.GetCount());
|
||||
for (uint k = 0; k < g->material_table.GetCount(); ++k)
|
||||
sg->material_table[k] = g->material_table[k];
|
||||
|
||||
g = sg;
|
||||
}
|
||||
|
||||
// Prepare geometry.
|
||||
IGeometryTree *tree = new GeometryBIHTree;
|
||||
tree->BuildFromGeometry(gf, g);
|
||||
|
||||
// Build minmax for the transformed geometry.
|
||||
varray[obj_count] = g->ComputeMinMax(&o->GetMatrix());
|
||||
|
||||
obj[obj_count].g = g;
|
||||
obj[obj_count].tree = tree;
|
||||
obj[obj_count++].o = o;
|
||||
}
|
||||
bool SceneBIH::SetScene(ResourceFactory &gf, const S3D::Scene *s, bool shadow)
|
||||
{
|
||||
Free();
|
||||
|
||||
using namespace S3D;
|
||||
|
||||
SharedList <MObject *> objects;
|
||||
s->GetItemListByType(objects);
|
||||
SharedList <Instance *> instances;
|
||||
s->GetItemListByType(instances);
|
||||
|
||||
// Grab the scene content.
|
||||
uint obj_count = 0;
|
||||
ListForeachPtr(MObject *, o, objects)
|
||||
if (!o->geometry.IsEmpty())
|
||||
obj_count++;
|
||||
|
||||
// Count the instance objects.
|
||||
ListForeachPtr(Instance *, i, instances)
|
||||
{
|
||||
if (!i->instance_scene)
|
||||
{
|
||||
if (!(i->instance_scene = new Scene(s->GetVM())))
|
||||
continue;
|
||||
|
||||
i->instance_scene->FromMetaFileStoreGroup(i->template_path, &i->instance_group, SceneIOObject | SceneIOLight);
|
||||
if (i->instance_group != NULL)
|
||||
i->instance_group->SetRootItem(i);
|
||||
}
|
||||
|
||||
if (i->instance_group)
|
||||
ListForeachPtr(MItem *, ig, i->instance_group->GetItemList())
|
||||
if (ig->GetItemType() == Type_Object && !((MObject *)ig)->geometry.IsEmpty())
|
||||
obj_count++;
|
||||
}
|
||||
|
||||
if (!obj_count)
|
||||
return true;
|
||||
|
||||
if (!obj.Allocate(obj_count))
|
||||
__ERR__(__LOG_E__ << "Failed to grab scene to raytracer.\n", false)
|
||||
|
||||
// Build scene tree and object trees.
|
||||
Array <MinMax> varray(obj_count);
|
||||
if (!varray)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate volume array to build scene tree.\n", false)
|
||||
|
||||
obj_count = 0;
|
||||
|
||||
ListForeachPtr(MObject *, o, objects)
|
||||
AddObject(gf, o, obj_count, varray, shadow);
|
||||
|
||||
// Add the instance objects.
|
||||
ListForeachPtr(Instance *, i, instances)
|
||||
if (i->instance_group)
|
||||
ListForeachPtr(MItem *, ig, i->instance_group->GetItemList())
|
||||
if (ig->GetItemType() == Type_Object && !((MObject *)ig)->geometry.IsEmpty())
|
||||
AddObject(gf, ((MObject *)ig), obj_count, varray, shadow);
|
||||
|
||||
// Build tree.
|
||||
if (!Build(obj_count, varray))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
void SceneBIH::Free()
|
||||
{
|
||||
obj.Free();
|
||||
Tree::Free();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
51
include/modules/raytracer/raytracer_spread.cpp
Normal file
51
include/modules/raytracer/raytracer_spread.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <cmath>
|
||||
#include "raytracer/raytracer_spread.h"
|
||||
#include "math/matrix3.h"
|
||||
#include "rand/rand.h"
|
||||
#include "memory/memory.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::Raytrace;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Spread::Initialize(uint u_count, uint v_count, float max_spread)
|
||||
{
|
||||
Free();
|
||||
|
||||
if (!spread.Allocate(u_count * v_count))
|
||||
__ERR__(__LOG_E__ << "failed to allocate vector spread.\n", false)
|
||||
|
||||
float s_v = max_spread / (v_count + 2), a_v = s_v;
|
||||
|
||||
uint count = 0;
|
||||
for (uint v = 0; v < v_count; ++v)
|
||||
{
|
||||
float strat_v = a_v + Random::FRand(s_v); // Stratified sampling.
|
||||
|
||||
float s_u = Units::Deg(360.f) / u_count, a_u = Units::Deg(0.f);
|
||||
for (uint u = 0; u < u_count; ++u)
|
||||
{
|
||||
float strat_u = a_u + Random::FRand(s_u); // Stratified sampling.
|
||||
|
||||
Vector4 tmp(sin(strat_v), 0, cos(strat_v));
|
||||
Matrix3 rtz(Matrix3::RotationMatrixZAxis(strat_u));
|
||||
rtz.Apply(&spread[count++], &tmp);
|
||||
|
||||
a_u += s_u;
|
||||
}
|
||||
a_v += s_v;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void Spread::Free()
|
||||
{
|
||||
spread.Free();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
296
include/modules/raytracer/shader_tree_cpu.cpp
Normal file
296
include/modules/raytracer/shader_tree_cpu.cpp
Normal file
@ -0,0 +1,296 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <cmath>
|
||||
#include "raytracer/raytracer_core.h"
|
||||
#include "core/shader_block.h"
|
||||
#include "core/geometry.h"
|
||||
#include "core/object.h"
|
||||
|
||||
using namespace GS::Core;
|
||||
using namespace GS::Raytrace;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Raytracer::EvaluateShaderBlock(const Trace &trace, const ShaderBlock *block, ShaderBlockValue &out)
|
||||
{
|
||||
ShaderBlockValue in[4]; // No more than 4 inputs supported.
|
||||
|
||||
// Validity check.
|
||||
if (!block)
|
||||
return true;
|
||||
|
||||
// Evaluate inputs.
|
||||
for (uint n = 0; n < block->GetInputCount(); ++n)
|
||||
if (!EvaluateShaderBlock(trace, block->GetInput(n), in[n]))
|
||||
return false;
|
||||
|
||||
// Evaluate block.
|
||||
switch (block->type)
|
||||
{
|
||||
case ShaderBlock::TypeGeometryVertex:
|
||||
out.Set(trace.pi * trace.o->GetInverseMatrix());
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeGeometryNormal:
|
||||
if (Vector4 *nrm = trace.g->vtx_normal)
|
||||
{
|
||||
Vector4 &nm0 = nrm[trace.bi],
|
||||
&nm1 = nrm[trace.bi + trace.it + 1],
|
||||
&nm2 = nrm[trace.bi + trace.it + 2];
|
||||
|
||||
out.Set(nm0 * trace.w + nm1 * trace.u + nm2 * trace.v);
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeGeometryVertexColor:
|
||||
if (Vector4 *rgb = trace.g->rgb)
|
||||
{
|
||||
Vector4 &cl0 = rgb[trace.bi],
|
||||
&cl1 = rgb[trace.bi + trace.it + 1],
|
||||
&cl2 = rgb[trace.bi + trace.it + 2];
|
||||
|
||||
out.Set(cl0 * trace.w + cl1 * trace.u + cl2 * trace.v);
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeGeometryUV:
|
||||
{
|
||||
GeometryUVShaderBlock *b = (GeometryUVShaderBlock *)block;
|
||||
|
||||
if (Vector2 *uv = trace.g->uv[b->channel])
|
||||
{
|
||||
Vector2 &uv0 = uv[trace.bi],
|
||||
&uv1 = uv[trace.bi + trace.it + 1],
|
||||
&uv2 = uv[trace.bi + trace.it + 2];
|
||||
|
||||
out.Set(Vector4(trace.w * uv0.x + trace.u * uv1.x + trace.v * uv2.x, trace.w * uv0.y + trace.u * uv1.y + trace.v * uv2.y, 0, 0));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeGeometrySkinning:
|
||||
break;
|
||||
case ShaderBlock::TypeGeometryTangentFrame:
|
||||
{
|
||||
Vector4 sample = ( trace.g->vtx_normal[trace.bi] * trace.w +
|
||||
trace.g->vtx_normal[trace.bi + trace.it + 1] * trace.u +
|
||||
trace.g->vtx_normal[trace.bi + trace.it + 2] * trace.v ).Normalized();
|
||||
|
||||
Vector4 T, B;
|
||||
|
||||
if (trace.g->vtx_tangent)
|
||||
{
|
||||
// Interpolated tangent basis.
|
||||
T = (trace.g->vtx_tangent[trace.bi + 0].T * trace.w +
|
||||
trace.g->vtx_tangent[trace.bi + trace.it + 1].T * trace.u +
|
||||
trace.g->vtx_tangent[trace.bi + trace.it + 2].T * trace.v ).Normalized();
|
||||
B = (trace.g->vtx_tangent[trace.bi + 0].B * trace.w +
|
||||
trace.g->vtx_tangent[trace.bi + trace.it + 1].B * trace.u +
|
||||
trace.g->vtx_tangent[trace.bi + trace.it + 2].B * trace.v ).Normalized();
|
||||
}
|
||||
else
|
||||
{
|
||||
T.Set(1, 0, 0);
|
||||
B.Set(0, 1, 0);
|
||||
}
|
||||
|
||||
// Build tangent frame.
|
||||
Matrix3 tangent_matrix(T, B, sample);
|
||||
out.Set(tangent_matrix);
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeTexture:
|
||||
out.Set(((TextureShaderBlock *)block)->texture);
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeTextureSampler:
|
||||
{
|
||||
if (in[0].t)
|
||||
{
|
||||
Color sample;
|
||||
if (Picture *p = gf->LoadPicture(in[0].t))
|
||||
p->SampleRGBA(in[1].v.x < 0 ? 1 + fmodf(in[1].v.x, 1) : fmodf(in[1].v.x, 1), in[1].v.y < 0 ? 1 + fmodf(in[1].v.y, 1) : fmodf(in[1].v.y, 1), sample);
|
||||
out.Set(sample);
|
||||
}
|
||||
else
|
||||
out.Set(Vector4(0, 0, 0));
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeConstant:
|
||||
{
|
||||
ConstantShaderBlock *b = (ConstantShaderBlock *)block;
|
||||
out.Set(Vector4(b->constant[0], b->constant[1], b->constant[2], b->constant[3]));
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeColor:
|
||||
{
|
||||
ColorShaderBlock *b = (ColorShaderBlock *)block;
|
||||
out.Set(b->color);
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeMaterialParam:
|
||||
{
|
||||
MaterialParamShaderBlock *b = (MaterialParamShaderBlock *)block;
|
||||
switch (b->param)
|
||||
{
|
||||
case MaterialParamShaderBlock::MaterialAmbient:
|
||||
out.Set(trace.m->ambient);
|
||||
break;
|
||||
case MaterialParamShaderBlock::MaterialDiffuse:
|
||||
out.Set(trace.m->diffuse);
|
||||
break;
|
||||
case MaterialParamShaderBlock::MaterialSpecular:
|
||||
out.Set(trace.m->specular);
|
||||
break;
|
||||
case MaterialParamShaderBlock::MaterialSelf:
|
||||
out.Set(trace.m->self);
|
||||
break;
|
||||
case MaterialParamShaderBlock::MaterialGlossiness:
|
||||
out.Set(trace.m->glossiness);
|
||||
break;
|
||||
case MaterialParamShaderBlock::MaterialOpacity:
|
||||
out.Set(trace.m->opacity);
|
||||
break;
|
||||
case MaterialParamShaderBlock::MaterialReflection:
|
||||
out.Set(trace.m->reflection);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeScreenUV:
|
||||
out.Set(Vector4(0.5f,0.5f,0.5f));
|
||||
break;
|
||||
case ShaderBlock::TypeViewVector:
|
||||
out.Set(trace.d);
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeNormalViewMatrix:
|
||||
out.Set(Matrix3::FromOrthonormalBasis(trace.d).Transposed() * trace.o->GetRotationMatrix());
|
||||
break;
|
||||
case ShaderBlock::TypeNormalMatrix:
|
||||
out.Set(trace.o->GetRotationMatrix());
|
||||
break;
|
||||
case ShaderBlock::TypeModelViewMatrix:
|
||||
{
|
||||
Matrix4 view_matrix = Matrix4::FromMatrix3(Matrix3::FromOrthonormalBasis(trace.d).Transposed());
|
||||
view_matrix.SetRow(3, trace.s.Reversed());
|
||||
out.Set(view_matrix * trace.o->GetMatrix());
|
||||
}
|
||||
break;
|
||||
case ShaderBlock::TypeModelMatrix:
|
||||
out.Set(trace.o->GetMatrix());
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeMix: out.Set(in[0].v * in[2].v.x + in[1].v * (1 - in[2].v.x)); break;
|
||||
case ShaderBlock::TypeAdd: out.Set(in[0].v + in[1].v); break;
|
||||
case ShaderBlock::TypeMul:
|
||||
{
|
||||
if (in[0].type == in[1].type)
|
||||
switch (in[0].type)
|
||||
{
|
||||
case ShaderBlockValue::BlockValueVector: out.Set(in[0].v * in[1].v); break;
|
||||
case ShaderBlockValue::BlockValueMatrix3: out.Set(in[0].m3 * in[1].m3); break;
|
||||
case ShaderBlockValue::BlockValueMatrix4: out.Set(in[0].m4 * in[1].m4); break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShaderBlockValue *_a = &in[0], *_b = &in[1];
|
||||
if (_b->type < _a->type)
|
||||
{ ShaderBlockValue *tmp = _a; _a = _b; _b = tmp; }
|
||||
|
||||
if (_a->type == ShaderBlockValue::BlockValueVector)
|
||||
{
|
||||
if (_b->type == ShaderBlockValue::BlockValueMatrix3)
|
||||
out.Set(_a->v * _b->m3);
|
||||
else if (_b->type == ShaderBlockValue::BlockValueMatrix4)
|
||||
out.Set(_a->v * _b->m4);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeSub: out.Set(in[0].v - in[1].v); break;
|
||||
case ShaderBlock::TypeDiv: out.Set(in[0].v / in[1].v); break;
|
||||
|
||||
case ShaderBlock::TypeDot: out.Set(in[0].v.Dot(in[1].v)); break;
|
||||
case ShaderBlock::TypeCross: out.Set(in[0].v.Cross(in[1].v)); break;
|
||||
|
||||
case ShaderBlock::TypeClamp:
|
||||
out.Set(Vector4(
|
||||
Types::Clamp(in[0].v.x, in[1].v.x, in[2].v.x),
|
||||
Types::Clamp(in[0].v.y, in[1].v.y, in[2].v.y),
|
||||
Types::Clamp(in[0].v.z, in[1].v.z, in[2].v.z),
|
||||
Types::Clamp(in[0].v.w, in[1].v.w, in[2].v.w) ) );
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeNormalize: out.Set(in[0].v.Normalized()); break;
|
||||
|
||||
case ShaderBlock::TypeSwizzle:
|
||||
{
|
||||
SwizzleShaderBlock *b = (SwizzleShaderBlock *)block;
|
||||
|
||||
Vector4 v(0, 0, 0);
|
||||
for (int n = 0; n < 4; ++n)
|
||||
if (b->swizzle[n] != SwizzleShaderBlock::SwizzleNone)
|
||||
v[n] = in[0].v[b->swizzle[n] - SwizzleShaderBlock::SwizzleX];
|
||||
|
||||
out.Set(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeBuild:
|
||||
{
|
||||
BuildShaderBlock *b = (BuildShaderBlock *)block;
|
||||
|
||||
Vector4 v(0, 0, 0);
|
||||
for (int n = 0; n < 4; ++n)
|
||||
{
|
||||
if (b->build[n] == BuildShaderBlock::BuildOne)
|
||||
v[n] = 1;
|
||||
else if (b->build[n] == BuildShaderBlock::BuildZero)
|
||||
v[n] = 0;
|
||||
else v[n] = in[n].v[b->build[n] - BuildShaderBlock::BuildX];
|
||||
}
|
||||
|
||||
out.Set(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeSin: out.Set(sin(in[0].v.x)); break;
|
||||
case ShaderBlock::TypeCos: out.Set(cos(in[0].v.x)); break;
|
||||
|
||||
case ShaderBlock::TypeUnpackColorToVector:
|
||||
out.Set((in[0].v - Vector4(0.5, 0.5, 0.0)) * Vector4(2.0, 2.0, 1.0));
|
||||
break;
|
||||
case ShaderBlock::TypePackVectorToColor:
|
||||
out.Set((in[0].v + Vector4(1.0, 1.0, 0.0)) * Vector4(0.5, 0.5, 1.0));
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeClock:
|
||||
out.Set(render_clock);
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypePow:
|
||||
out.Set(float(pow(in[0].v.x, in[1].v.x)));
|
||||
break;
|
||||
|
||||
case ShaderBlock::TypeAbs:
|
||||
if (in[0].type == ShaderBlockValue::BlockValueVector)
|
||||
{
|
||||
Vector4 o = in[0].v.Abs();
|
||||
out.Set(Vector4(o.x, o.y, o.z));
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
103
include/modules/script_squirrel/cobject/cobject.cpp
Normal file
103
include/modules/script_squirrel/cobject/cobject.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "script_squirrel/cobject/cobject.h"
|
||||
#include "script_squirrel/engine_vm.h"
|
||||
#include "raytracer/raytracer_core.h"
|
||||
#include "automation/automation_source_group.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/group.h"
|
||||
#include "scene3d/memitter.h"
|
||||
#include "scene3d/mcamera.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/mtrigger.h"
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/instance.h"
|
||||
#include "ui/ui_cursor.h"
|
||||
#include "core/raster_font.h"
|
||||
#include "input/input_device.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void CObject::Initialize(CObjectType t, void *o, bool m)
|
||||
{
|
||||
Release();
|
||||
|
||||
type = t;
|
||||
native = o;
|
||||
managed = m;
|
||||
|
||||
if (native)
|
||||
switch (type)
|
||||
{
|
||||
case typetag_Picture: ((Picture *)native)->AddRef(); break;
|
||||
case typetag_Texture: ((Render::Texture *)native)->AddRef(); break;
|
||||
case typetag_Geometry: ((Render::Geometry *)native)->AddRef(); break;
|
||||
case typetag_Material: ((Render::Material *)native)->AddRef(); break;
|
||||
case typetag_InputDevice: ((Input::Device *)native)->AddRef(); break;
|
||||
case typetag_AutomationSource: ((Automation::Source *)native)->AddRef(); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
void CObject::Release()
|
||||
{
|
||||
if (native == NULL)
|
||||
return;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case typetag_Picture: ((Picture *)native)->RemoveRef(); break;
|
||||
case typetag_Texture: ((Render::Texture *)native)->RemoveRef(); break;
|
||||
case typetag_Geometry: ((Render::Geometry *)native)->RemoveRef(); break;
|
||||
case typetag_Material: ((Render::Material *)native)->RemoveRef(); break;
|
||||
case typetag_InputDevice: ((Input::Device *)native)->RemoveRef(); break;
|
||||
case typetag_AutomationSource: ((Automation::Source *)native)->RemoveRef(); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (managed)
|
||||
switch (type)
|
||||
{
|
||||
case typetag_Metafile: delete ((NML::File *)native); break;
|
||||
case typetag_Raytracer: delete ((Raytrace::Raytracer *)native); break;
|
||||
case typetag_RasterFont: delete ((Render::RasterFont *)native); break;
|
||||
case typetag_AutomationSourceGroup: delete ((Automation::SourceGroup *)native); break;
|
||||
case typetag_Group: delete ((S3D::Group *)native); break;
|
||||
case typetag_Scene3d: delete ((S3D::Scene *)native); break;
|
||||
case typetag_UICursor: delete ((S2D::Cursor *)native); break;
|
||||
|
||||
default:
|
||||
__LOG_E__ << "Type " << CObjectTypeToString(type) << " should not be managed by the VM.\n";
|
||||
break;
|
||||
}
|
||||
|
||||
native = NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
CObject::CObject(EngineVM *v, CObjectType t, void *o, bool managed) : vm(v)
|
||||
{
|
||||
list_item = vm->cobjects.Add(this);
|
||||
|
||||
native = NULL;
|
||||
Initialize(t, o, managed);
|
||||
}
|
||||
CObject::~CObject()
|
||||
{
|
||||
if (list_item)
|
||||
{
|
||||
vm->cobjects.Remove(list_item);
|
||||
// g_flog << "Native object alive count: " << vm->cobjects.GetCount() << "\n";
|
||||
}
|
||||
Release();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
154
include/modules/script_squirrel/cobject/cobject_impl.cpp
Normal file
154
include/modules/script_squirrel/cobject/cobject_impl.cpp
Normal file
@ -0,0 +1,154 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "script_squirrel/cobject/cobject_decl.h"
|
||||
#include "script_squirrel/cobject/cobject.h"
|
||||
#include "script_squirrel/squirrel_vm.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool CObject::GetBase(HSQUIRRELVM vm, int idx, void **o, CObjectType *types)
|
||||
{
|
||||
// get object type
|
||||
CObjectType type;
|
||||
if (!GetType(vm, idx, type))
|
||||
return false;
|
||||
|
||||
// cast to target type if compatible
|
||||
for (int n = 0; types[n] != typetag_Undefined; ++n)
|
||||
if (type == types[n])
|
||||
return Get(vm, idx, (void **)o);
|
||||
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static SQInteger CObject_release_hook(SQUserPointer p, SQInteger size)
|
||||
{
|
||||
if (CObject *pv = (CObject *)p)
|
||||
delete pv;
|
||||
return 0;
|
||||
}
|
||||
bool push_CObject(HSQUIRRELVM vm, const CObject &quat)
|
||||
{
|
||||
CObject *newquat = new CObject((EngineVM *)sq_getforeignptr(vm));
|
||||
*newquat = quat;
|
||||
if (!CreateNativeClassInstance(vm, "CObject", newquat, CObject_release_hook))
|
||||
{
|
||||
delete newquat;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
::SquirrelObject new_CObject(HSQUIRRELVM vm, const CObject &quat)
|
||||
{
|
||||
::SquirrelObject ret(vm);
|
||||
if (push_CObject(vm, quat))
|
||||
{
|
||||
ret.AttachToStackObject(-1);
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int construct_CObject(HSQUIRRELVM vm, CObject *p)
|
||||
{
|
||||
sq_setinstanceup(vm, 1, p);
|
||||
sq_setreleasehook(vm, 1, CObject_release_hook);
|
||||
return 1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool CObject::Push(HSQUIRRELVM v, void *_ptr, CObjectType _type, bool managed)
|
||||
{
|
||||
CObject *o = new CObject((EngineVM *)sq_getforeignptr(v), _type, _ptr, managed);
|
||||
|
||||
if (!CreateNativeClassInstance(v, "CObject", o, CObject_release_hook))
|
||||
{
|
||||
__LOG_E__ << "Could not allocate native reference.\n";
|
||||
_safe_delete(o);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool CObject::GetType(HSQUIRRELVM v, int idx, CObjectType &type)
|
||||
{
|
||||
StackHandler sa(v);
|
||||
|
||||
CObject *self;
|
||||
if (SQ_FAILED(sq_getinstanceup(v, idx, (SQUserPointer*)&self, (SQUserPointer)&__CObject_decl)))
|
||||
return false;
|
||||
|
||||
__ASSERT__(self != NULL);
|
||||
|
||||
type = self->type;
|
||||
return true;
|
||||
}
|
||||
bool CObject::Get(HSQUIRRELVM v, int idx, void **p, CObjectType type)
|
||||
{
|
||||
__ASSERT__(p != NULL);
|
||||
|
||||
StackHandler sa(v);
|
||||
|
||||
CObject *self;
|
||||
if (SQ_FAILED(sq_getinstanceup(v, idx, (SQUserPointer*)&self, (SQUserPointer)&__CObject_decl)))
|
||||
return false;
|
||||
|
||||
__ASSERT__(self != NULL);
|
||||
|
||||
if ((type != typetag_Undefined) && (self->type != type))
|
||||
{
|
||||
sq_throwerror(v, String::Format("Native reference to '%s' expected, got '%s'", CObjectTypeToString(type), CObjectTypeToString(self->type)));
|
||||
return false;
|
||||
}
|
||||
|
||||
p[0] = self->native;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(CObject, constructor)
|
||||
return construct_CObject(v, new CObject((EngineVM *)sq_getforeignptr(v)));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(CObject, _cmp)
|
||||
_GetSelf(CObject, CObject);
|
||||
_GetTypedParam(object, 2, CObject, CObject);
|
||||
return sa.Return(asbool(self->native == object->native));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(CObject, type)
|
||||
_GetSelf(CObject, CObject);
|
||||
return sa.Return((int)self->type);
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(CObject, isValid)
|
||||
_GetSelf(CObject, CObject);
|
||||
return sa.Return(asbool(self->native));
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(CObject, isNull)
|
||||
_GetSelf(CObject, CObject);
|
||||
return sa.Return(!asbool(self->native));
|
||||
_END_IMPL
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_BEGIN_CLASS(CObject)
|
||||
|
||||
_MEMBER_FUNCTION(CObject, constructor, -1, ".")
|
||||
_MEMBER_FUNCTION(CObject, _cmp, 2, ".xx")
|
||||
|
||||
_MEMBER_FUNCTION(CObject, isValid, 1, _SC("."))
|
||||
_MEMBER_FUNCTION(CObject, isNull, 1, _SC("."))
|
||||
_MEMBER_FUNCTION(CObject, type, 1, _SC("."))
|
||||
|
||||
_END_CLASS(CObject)
|
||||
//------------------------------------------------------------------------------
|
||||
@ -0,0 +1,206 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __COBJECT_GEOMETRY_TEMPLATE_IMPL__
|
||||
#define __COBJECT_GEOMETRY_TEMPLATE_IMPL__
|
||||
|
||||
|
||||
#include "script_squirrel/cobject/geometry_template_decl.h"
|
||||
#include "script_squirrel/cobject/cobject_decl.h"
|
||||
#include "script_squirrel/cobject/vector_decl.h"
|
||||
#include "script_squirrel/cobject/uv_decl.h"
|
||||
#include "script_squirrel/cobject/cobject.h"
|
||||
#include "core/geometry_template.h"
|
||||
#include "core/resource_factories.h"
|
||||
#include "core/render_resource_factory.h"
|
||||
#include "core/render_data.h"
|
||||
#include "core/renderer.h"
|
||||
#include "core/engine.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#define _GetGeometryTemplate(_VAR, _IDX) _GetTypedParam(_VAR, _IDX, GeometryTemplate, GeometryTemplate)
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
_IMPL_NATIVE_CONSTRUCTION(GeometryTemplate, GeometryTemplate);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(GeometryTemplate, constructor)
|
||||
return construct_GeometryTemplate(v, new GeometryTemplate);
|
||||
_END_IMPL
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(GeometryTemplate, clearMaterial)
|
||||
_GetGeometryTemplate(t, 1)
|
||||
t->ClearMaterials();
|
||||
return 0;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(GeometryTemplate, pushMaterial)
|
||||
_GetGeometryTemplate(t, 1)
|
||||
const SQChar *name = sa.GetString(2);
|
||||
t->PushMaterial(name);
|
||||
return 0;
|
||||
_END_IMPL
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(GeometryTemplate, clear)
|
||||
_GetGeometryTemplate(t, 1)
|
||||
t->Clear();
|
||||
return 0;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(GeometryTemplate, beginPolygon)
|
||||
_GetGeometryTemplate(t, 1)
|
||||
t->BeginPolygon();
|
||||
return 0;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(GeometryTemplate, pushVertex)
|
||||
_GetGeometryTemplate(t, 1)
|
||||
_GetTypedParam(_v, 2, Vector4, Vector)
|
||||
t->PushVertex(*_v);
|
||||
return 0;
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(GeometryTemplate, pushNormal)
|
||||
_GetGeometryTemplate(t, 1)
|
||||
_GetTypedParam(n, 2, Vector4, Vector)
|
||||
t->PushNormal(*n);
|
||||
return 0;
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(GeometryTemplate, pushColor)
|
||||
_GetGeometryTemplate(t, 1)
|
||||
_GetTypedParam(c, 2, Vector4, Vector)
|
||||
t->PushColor(Color(*c));
|
||||
return 0;
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(GeometryTemplate, pushUV)
|
||||
_GetGeometryTemplate(t, 1)
|
||||
_GetTypedParam(uv, 3, Vector2, UV)
|
||||
t->PushUV(sa.GetInt(2), *uv);
|
||||
return 0;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(GeometryTemplate, endPolygon)
|
||||
_GetGeometryTemplate(t, 1)
|
||||
t->EndPolygon((ushort)sa.GetInt(2));
|
||||
return 0;
|
||||
_END_IMPL
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(GeometryTemplate, setVertexMergeThreshold)
|
||||
_GetGeometryTemplate(t, 1)
|
||||
t->SetVertexMergeThreshold(sa.GetFloat(2));
|
||||
return 0;
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(GeometryTemplate, instantiate)
|
||||
_GetGeometryTemplate(t, 1)
|
||||
_GetCObject(ResourceFactories, typetag_ResourceFactories, f, 2)
|
||||
AutoPtr <Geometry> g(t->Instantiate(sa.GetString(3)));
|
||||
Render::Geometry *r = f->render->NewGeometry();
|
||||
r->Create(*f->render, *g);
|
||||
_ReturnCObject(r, typetag_Geometry)
|
||||
_END_IMPL
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//# Class: GeometryTemplate
|
||||
_BEGIN_CLASS(GeometryTemplate)
|
||||
|
||||
_MEMBER_FUNCTION(GeometryTemplate, constructor, 1, _SC("."))
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//# Topic: Polygon creation
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*#
|
||||
Func: beginPolygon
|
||||
Proto: void:
|
||||
Desc: Begin declaration of a new polygon.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(GeometryTemplate, beginPolygon, 1, _SC("."))
|
||||
/*#
|
||||
Func: pushVertex
|
||||
Proto: void:Vector
|
||||
Desc: Push a vertex on the current polygon declaration.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(GeometryTemplate, pushVertex, 2, _SC(".x"))
|
||||
/*#
|
||||
Func: pushNormal
|
||||
Proto: void:Vector
|
||||
Desc: Push a normal on the current polygon declaration.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(GeometryTemplate, pushNormal, 2, _SC(".x"))
|
||||
/*#
|
||||
Func: pushColor
|
||||
Proto: void:Vector
|
||||
Desc: Push a color on the current polygon declaration.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(GeometryTemplate, pushColor, 2, _SC(".x"))
|
||||
/*#
|
||||
Func: pushUV
|
||||
Proto: void:int channel, UV
|
||||
Desc: Push an UV on a channel of the current polygon declaration.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(GeometryTemplate, pushUV, 3, _SC(".ix"))
|
||||
/*#
|
||||
Func: endPolygon
|
||||
Proto: void:int material
|
||||
Desc: End declaration of the current polygon and specify its material index.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(GeometryTemplate, endPolygon, 2, _SC(".i"))
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//# Topic: Geometry creation
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*#
|
||||
Func: clear
|
||||
Proto: void:
|
||||
Desc: Clear current template definition, keep the current material table.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(GeometryTemplate, clear, 1, _SC("."))
|
||||
|
||||
/*#
|
||||
Func: instantiate
|
||||
Proto: Geometry:Engine engine, string name
|
||||
Desc: Instantiate the current template as a named geometry.
|
||||
Note: If the geometry name is already found in the current engine cache, a
|
||||
cached copy will be returned instead of a new instantiation.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(GeometryTemplate, instantiate, 3, _SC(".xs"))
|
||||
|
||||
/*#
|
||||
Func: clearMaterial
|
||||
Proto: void:
|
||||
Desc: Push a material on the template material table.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(GeometryTemplate, clearMaterial, 1, _SC("."))
|
||||
/*#
|
||||
Func: pushMaterial
|
||||
Proto: void:String path
|
||||
Desc: Push a material path on the template material table.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(GeometryTemplate, pushMaterial, 2, _SC(".s"))
|
||||
|
||||
/*#
|
||||
Func: setVertexMergeThreshold
|
||||
Proto: void:float threshold
|
||||
Desc: Set the vertex merging algorithm threshold.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(GeometryTemplate, setVertexMergeThreshold, 2, _SC(".n"))
|
||||
|
||||
_END_CLASS(GeometryTemplate)
|
||||
|
||||
|
||||
#endif // __COBJECT_GEOMETRY_TEMPLATE_IMPL__
|
||||
643
include/modules/script_squirrel/cobject/matrix_impl.cpp
Normal file
643
include/modules/script_squirrel/cobject/matrix_impl.cpp
Normal file
@ -0,0 +1,643 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include "script_squirrel/cobject/matrix_decl.h"
|
||||
#include "script_squirrel/cobject/vector_decl.h"
|
||||
#include "math/matrix4.h"
|
||||
#include "math/matrix3.h"
|
||||
#include "math/quaternion.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
#ifndef _T
|
||||
#define _T
|
||||
#endif
|
||||
|
||||
_DECL_CLASS(Matrix4)
|
||||
_IMPL_NATIVE_CONSTRUCTION(Matrix4, Matrix4)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, constructor)
|
||||
Matrix4 temp;
|
||||
int nparams = sa.GetParamCount();
|
||||
|
||||
switch (nparams)
|
||||
{
|
||||
case 1: temp.Set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); break;
|
||||
case 5:
|
||||
{
|
||||
_GetTypedParam(_u, 2, Vector4, Vector);
|
||||
_GetTypedParam(_v, 3, Vector4, Vector);
|
||||
_GetTypedParam(_w, 4, Vector4, Vector);
|
||||
_GetTypedParam(_x, 5, Vector4, Vector);
|
||||
|
||||
if (_u && _v && _w && _x)
|
||||
{ temp.Set(_u->x, _u->y, _u->z, _u->w, _v->x, _v->y, _v->z, _v->w, _w->x, _w->y, _w->z, _w->w, _x->x, _x->y, _x->z, _x->w); }
|
||||
else
|
||||
return sa.ThrowError("Matrix4() invalid parameters");
|
||||
}
|
||||
break;
|
||||
|
||||
case 17:
|
||||
temp.Set(
|
||||
sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4), sa.GetFloat(5),
|
||||
sa.GetFloat(6), sa.GetFloat(7), sa.GetFloat(8), sa.GetFloat(9),
|
||||
sa.GetFloat(10), sa.GetFloat(11), sa.GetFloat(12), sa.GetFloat(13),
|
||||
sa.GetFloat(14), sa.GetFloat(15), sa.GetFloat(16), sa.GetFloat(17)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
return sa.ThrowError("Matrix4() wrong parameter count");
|
||||
}
|
||||
return construct_Matrix4(v, new Matrix4(temp));
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// The string class is used to speed up comparison as it uses a hash-based early
|
||||
// rejection.
|
||||
static String uc_m00("m00"), uc_m10("m10"), uc_m20("m20"), uc_m30("m30"),
|
||||
uc_m01("m01"), uc_m11("m11"), uc_m21("m21"), uc_m31("m31"),
|
||||
uc_m02("m02"), uc_m12("m12"), uc_m22("m22"), uc_m32("m32"),
|
||||
uc_m03("m03"), uc_m13("m13"), uc_m23("m23"), uc_m33("m33");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, _set)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
case OT_STRING:
|
||||
{
|
||||
String idx(sa.GetString(2));
|
||||
|
||||
if (idx == uc_m00) return sa.Return(self->m[0][0] = sa.GetFloat(3));
|
||||
if (idx == uc_m10) return sa.Return(self->m[1][0] = sa.GetFloat(3));
|
||||
if (idx == uc_m20) return sa.Return(self->m[2][0] = sa.GetFloat(3));
|
||||
if (idx == uc_m30) return sa.Return(self->m[3][0] = sa.GetFloat(3));
|
||||
if (idx == uc_m01) return sa.Return(self->m[0][1] = sa.GetFloat(3));
|
||||
if (idx == uc_m11) return sa.Return(self->m[1][1] = sa.GetFloat(3));
|
||||
if (idx == uc_m21) return sa.Return(self->m[2][1] = sa.GetFloat(3));
|
||||
if (idx == uc_m31) return sa.Return(self->m[3][1] = sa.GetFloat(3));
|
||||
if (idx == uc_m02) return sa.Return(self->m[0][2] = sa.GetFloat(3));
|
||||
if (idx == uc_m12) return sa.Return(self->m[1][2] = sa.GetFloat(3));
|
||||
if (idx == uc_m22) return sa.Return(self->m[2][2] = sa.GetFloat(3));
|
||||
if (idx == uc_m32) return sa.Return(self->m[3][2] = sa.GetFloat(3));
|
||||
if (idx == uc_m03) return sa.Return(self->m[0][3] = sa.GetFloat(3));
|
||||
if (idx == uc_m13) return sa.Return(self->m[1][3] = sa.GetFloat(3));
|
||||
if (idx == uc_m23) return sa.Return(self->m[2][3] = sa.GetFloat(3));
|
||||
if (idx == uc_m33) return sa.Return(self->m[3][3] = sa.GetFloat(3));
|
||||
}
|
||||
break;
|
||||
}
|
||||
return SQ_ERROR;
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, _get)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
case OT_STRING:
|
||||
{
|
||||
String idx(sa.GetString(2));
|
||||
|
||||
if (idx == uc_m00) return sa.Return(self->m[0][0]);
|
||||
if (idx == uc_m10) return sa.Return(self->m[1][0]);
|
||||
if (idx == uc_m20) return sa.Return(self->m[2][0]);
|
||||
if (idx == uc_m30) return sa.Return(self->m[3][0]);
|
||||
if (idx == uc_m01) return sa.Return(self->m[0][1]);
|
||||
if (idx == uc_m11) return sa.Return(self->m[1][1]);
|
||||
if (idx == uc_m21) return sa.Return(self->m[2][1]);
|
||||
if (idx == uc_m31) return sa.Return(self->m[3][1]);
|
||||
if (idx == uc_m02) return sa.Return(self->m[0][2]);
|
||||
if (idx == uc_m12) return sa.Return(self->m[1][2]);
|
||||
if (idx == uc_m22) return sa.Return(self->m[2][2]);
|
||||
if (idx == uc_m32) return sa.Return(self->m[3][2]);
|
||||
if (idx == uc_m03) return sa.Return(self->m[0][3]);
|
||||
if (idx == uc_m13) return sa.Return(self->m[1][3]);
|
||||
if (idx == uc_m23) return sa.Return(self->m[2][3]);
|
||||
if (idx == uc_m33) return sa.Return(self->m[3][3]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return SQ_ERROR;
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, GetRow)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(sa.GetInt(2))));
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, SetRow)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_GetTypedParam(row, 3, Vector4, Vector)
|
||||
self->SetRow(sa.GetInt(2), *row);
|
||||
return 0;
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, GetColumn)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->GetColumn(sa.GetInt(2))));
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, SetColumn)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_GetTypedParam(col, 3, Vector4, Vector)
|
||||
self->SetColumn(sa.GetInt(2), *col);
|
||||
return 0;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, GetFront)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(2)));
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, GetBack)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(2).Reversed()));
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, GetUp)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(1)));
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, GetDown)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(1).Reversed()));
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, GetRight)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(0)));
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, GetLeft)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(0).Reversed()));
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, GetPosition)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(3)));
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, _mul)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_GetTypedParam(mtx, 2, Matrix4, Matrix4)
|
||||
_SA_RETURN_OBJECT(new_Matrix4(v, *self * *mtx));
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, AsMatrix3)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_SA_RETURN_OBJECT(new_Matrix3(v, Matrix3::FromMatrix4(*self)));
|
||||
_END_IMPL
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, GetInverseMatrix)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_SA_RETURN_OBJECT(new_Matrix4(v, self->InversedFast()));
|
||||
_END_IMPL
|
||||
//-----------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, Print)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
const char *label = "Matrix";
|
||||
if (sa.GetParamCount() == 2)
|
||||
label = sa.GetString(2);
|
||||
__LOG__ << "Dumping matrix '" << label << "':\n";
|
||||
for (int n = 0; n < 4; ++n)
|
||||
{
|
||||
Vector4 v = self->GetRow(n);
|
||||
__LOG__ << "Row " << n << ": { " << v.x << ", " << v.y << ", " << v.z << ", " << v.w << "}\n";
|
||||
}
|
||||
return 0;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Matrix4, RotationFromMatrix3)
|
||||
_GetSelf(Matrix4, Matrix4);
|
||||
_GetTypedParam(mtx, 2, Matrix3, Matrix3)
|
||||
self->m[0][0] = mtx->m[0][0]; self->m[1][0] = mtx->m[1][0]; self->m[2][0] = mtx->m[2][0];
|
||||
self->m[0][1] = mtx->m[0][1]; self->m[1][1] = mtx->m[1][1]; self->m[2][1] = mtx->m[2][1];
|
||||
self->m[0][2] = mtx->m[0][2]; self->m[1][2] = mtx->m[1][2]; self->m[2][2] = mtx->m[2][2];
|
||||
return 0;
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/*#
|
||||
Topic: Matrix
|
||||
Type: Matrix3
|
||||
Type: Matrix4
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: MatrixGeneric
|
||||
Desc: Global functions
|
||||
#*/
|
||||
/*#
|
||||
Func: Matrix3
|
||||
Proto: Matrix3:float m00...m33
|
||||
Desc: Create a new 3x3 matrix.
|
||||
Example:
|
||||
// Construct a default unity matrix.
|
||||
local a = Matrix3()
|
||||
// Vector based constructor.
|
||||
local b = Matrix3(v0, v1, v2)
|
||||
// Float based constructor.
|
||||
local c = Matrix3(m00, m10, m20, m01, m11, m21, m02, m12, m22)
|
||||
#*/
|
||||
/*#
|
||||
Func: Matrix4
|
||||
Proto: Matrix4:float m00...m44
|
||||
Desc: Create a new 4x4 matrix.
|
||||
Example:
|
||||
// Construct a default unity matrix.
|
||||
local a = Matrix4()
|
||||
// Vector based constructor.
|
||||
local b = Matrix4(v0, v1, v2, v3)
|
||||
// Float based constructor.
|
||||
local c = Matrix3(m00, m10, m20, m30, m01, m11, m21, m31, m02, m12, m22, m32, m03, m13, m23, m33)
|
||||
#*/
|
||||
/*#
|
||||
Func: RotationMatrixX
|
||||
Proto: Matrix3:float angle
|
||||
Desc: Create a 3x3 rotation matrix around the X axis, angle is in degree.
|
||||
Example: local m = RotationMatrixX(Deg(45))
|
||||
#*/
|
||||
/*#
|
||||
Func: RotationMatrixY
|
||||
Proto: Matrix3:float angle
|
||||
Desc: Create a 3x3 rotation matrix around the Y axis, angle is in degree.
|
||||
Example: local m = RotationMatrixY(Deg(45))
|
||||
#*/
|
||||
/*#
|
||||
Func: RotationMatrixZ
|
||||
Proto: Matrix3:float angle
|
||||
Desc: Create a 3x3 rotation matrix around the Z axis, angle is in degree.
|
||||
Example: local m = RotationMatrixZ(Deg(45))
|
||||
#*/
|
||||
/*#
|
||||
Func: MatrixToEuler
|
||||
Proto: Vector:Matrix3,RotationOrder
|
||||
Desc: Convert a world space matrix to Euler angles.
|
||||
#*/
|
||||
/*#
|
||||
Func: EulerFromDirection
|
||||
Proto: Vector:Vector direction
|
||||
Desc: Convert a world space direction vector to an Euler angle triplet (x, y, z).
|
||||
#*/
|
||||
/*#
|
||||
Func: EulerFromDirectionAndUp
|
||||
Proto: Vector:Vector direction,Vector up
|
||||
Desc: Convert a world space direction and up vectors to an Euler angle triplet (x, y, z).
|
||||
#*/
|
||||
/*#
|
||||
Func: RotationMatrixFromDirection
|
||||
Proto: Matrix3:Vector direction
|
||||
Desc: Convert a world space direction vector to a 3x3 rotation matrix.
|
||||
#*/
|
||||
/*#
|
||||
Func: RotationMatrixFromDirectionAndUp
|
||||
Proto: Matrix3:Vector direction,Vector up
|
||||
Desc: Convert a world space direction and up vectors to a 3x3 rotation matrix.
|
||||
#*/
|
||||
/*#
|
||||
Func: TransformationMatrix
|
||||
Proto: Matrix4:Vector position,Vector euler,Vector scale,Vector pivot
|
||||
Desc: Create a position, rotation, scale, offset 4x4 matrix.<br>The offset is applied first, scale second, rotation third and finally position is applied.
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: Matrix4Generic
|
||||
Desc: Matrix 4x4
|
||||
#*/
|
||||
_BEGIN_CLASS(Matrix4)
|
||||
_MEMBER_FUNCTION(Matrix4, constructor, -1, _T(". n|x n|x n|x n|x nnnn nnnn"))
|
||||
_MEMBER_FUNCTION(Matrix4, _get, 2, _T("xs"))
|
||||
_MEMBER_FUNCTION(Matrix4, _set, 3, _T("xsn"))
|
||||
_MEMBER_FUNCTION(Matrix4, _mul, 2, _T("xx"))
|
||||
|
||||
/*#
|
||||
Func: GetRow
|
||||
Proto: Vector:int index
|
||||
Desc: Return a matrix row as a vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, GetRow, 2, _T("xi"))
|
||||
/*#
|
||||
Func: SetRow
|
||||
Proto: void:int index, Vector row
|
||||
Desc: Set a matrix row from a vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, SetRow, 3, _T("xix"))
|
||||
/*#
|
||||
Func: GetColumn
|
||||
Proto: Vector:int index
|
||||
Desc: Return a matrix column as a vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, GetColumn, 2, _T("xi"))
|
||||
/*#
|
||||
Func: SetColumn
|
||||
Proto: void:int index, Vector column
|
||||
Desc: Set a matrix column from a vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, SetColumn, 3, _T("xix"))
|
||||
/*#
|
||||
Func: AsMatrix3
|
||||
Proto: Matrix3:
|
||||
Desc: Return matrix as a 3x3 matrix.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, AsMatrix3, 1, _T("x"))
|
||||
/*#
|
||||
Func: GetInverseMatrix
|
||||
Proto: Matrix4:
|
||||
Desc: Return inverse matrix.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, GetInverseMatrix, 1, _T("x"))
|
||||
/*#
|
||||
Func: Print
|
||||
Proto: void:
|
||||
Desc: Output matrix content to the engine log.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, Print, -1, _T("x"))
|
||||
/*#
|
||||
Func: RotationFromMatrix3
|
||||
Proto: void:Matrix3 orientation
|
||||
Desc: Set the rotation part of a 4x4 transformation matrix from a 3x3 matrix.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, RotationFromMatrix3, 2, _T("xx"))
|
||||
|
||||
/*#
|
||||
Section: Matrix4Component
|
||||
Desc: Transformation matrix component
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Func: GetFront
|
||||
Proto: Vector:
|
||||
Desc: Return the transformation matrix front axis vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, GetFront, 1, _T("x"))
|
||||
/*#
|
||||
Func: GetBack
|
||||
Proto: Vector:
|
||||
Desc: Return the transformation matrix down axis vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, GetBack, 1, _T("x"))
|
||||
/*#
|
||||
Func: GetRight
|
||||
Proto: Vector:
|
||||
Desc: Return the transformation matrix right axis vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, GetRight, 1, _T("x"))
|
||||
/*#
|
||||
Func: GetLeft
|
||||
Proto: Vector:
|
||||
Desc: Return the transformation matrix left axis vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, GetLeft, 1, _T("x"))
|
||||
/*#
|
||||
Func: GetUp
|
||||
Proto: Vector:
|
||||
Desc: Return the transformation matrix up axis vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, GetUp, 1, _T("x"))
|
||||
/*#
|
||||
Func: GetDown
|
||||
Proto: Vector:
|
||||
Desc: Return the transformation matrix down axis vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, GetDown, 1, _T("x"))
|
||||
/*#
|
||||
Func: GetPosition
|
||||
Proto: Vector:
|
||||
Desc: Return the transformation matrix position vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix4, GetPosition, 1, _T("x"))
|
||||
|
||||
_END_CLASS(Matrix4)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_DECL_CLASS(Matrix3);
|
||||
_IMPL_NATIVE_CONSTRUCTION(Matrix3, Matrix3);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix3, constructor)
|
||||
Matrix3 temp, *newv = NULL;
|
||||
int nparams = sa.GetParamCount();
|
||||
|
||||
switch (nparams)
|
||||
{
|
||||
case 1: temp.Set(1, 0, 0, 0, 1, 0, 0, 0, 1); break;
|
||||
case 4:
|
||||
{
|
||||
_GetTypedParam(_u, 2, Vector4, Vector);
|
||||
_GetTypedParam(_v, 3, Vector4, Vector);
|
||||
_GetTypedParam(_w, 4, Vector4, Vector);
|
||||
|
||||
if (_u && _v && _w)
|
||||
{ temp.Set(*_u, *_v, *_w); }
|
||||
else
|
||||
return sa.ThrowError("Matrix3() invalid parameters");
|
||||
}
|
||||
break;
|
||||
|
||||
case 10:
|
||||
temp.Set(
|
||||
sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4),
|
||||
sa.GetFloat(5), sa.GetFloat(6), sa.GetFloat(7),
|
||||
sa.GetFloat(8), sa.GetFloat(9), sa.GetFloat(10)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
return sa.ThrowError("Matrix3() wrong parameter count");
|
||||
}
|
||||
|
||||
newv = new Matrix3(temp);
|
||||
return construct_Matrix3(v, newv);
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix3, _set)
|
||||
_GetSelf(Matrix3, Matrix3);
|
||||
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
case OT_STRING:
|
||||
{
|
||||
String idx(sa.GetString(2));
|
||||
|
||||
if (idx == uc_m00) return sa.Return(self->m[0][0] = sa.GetFloat(3));
|
||||
if (idx == uc_m10) return sa.Return(self->m[1][0] = sa.GetFloat(3));
|
||||
if (idx == uc_m20) return sa.Return(self->m[2][0] = sa.GetFloat(3));
|
||||
if (idx == uc_m01) return sa.Return(self->m[0][1] = sa.GetFloat(3));
|
||||
if (idx == uc_m11) return sa.Return(self->m[1][1] = sa.GetFloat(3));
|
||||
if (idx == uc_m21) return sa.Return(self->m[2][1] = sa.GetFloat(3));
|
||||
if (idx == uc_m02) return sa.Return(self->m[0][2] = sa.GetFloat(3));
|
||||
if (idx == uc_m12) return sa.Return(self->m[1][2] = sa.GetFloat(3));
|
||||
if (idx == uc_m22) return sa.Return(self->m[2][2] = sa.GetFloat(3));
|
||||
}
|
||||
break;
|
||||
}
|
||||
return SQ_ERROR;
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix3, _get)
|
||||
_GetSelf(Matrix3, Matrix3);
|
||||
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
case OT_STRING:
|
||||
{
|
||||
String idx(sa.GetString(2));
|
||||
|
||||
if (idx == uc_m00) return sa.Return(self->m[0][0]);
|
||||
if (idx == uc_m10) return sa.Return(self->m[1][0]);
|
||||
if (idx == uc_m20) return sa.Return(self->m[2][0]);
|
||||
if (idx == uc_m01) return sa.Return(self->m[0][1]);
|
||||
if (idx == uc_m11) return sa.Return(self->m[1][1]);
|
||||
if (idx == uc_m21) return sa.Return(self->m[2][1]);
|
||||
if (idx == uc_m02) return sa.Return(self->m[0][2]);
|
||||
if (idx == uc_m12) return sa.Return(self->m[1][2]);
|
||||
if (idx == uc_m22) return sa.Return(self->m[2][2]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return SQ_ERROR;
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix3, GetRow)
|
||||
_GetSelf(Matrix3, Matrix3);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->GetRow(sa.GetInt(2))));
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(Matrix3, SetRow)
|
||||
_GetSelf(Matrix3, Matrix3);
|
||||
_GetTypedParam(row, 3, Vector4, Vector)
|
||||
self->SetRow(sa.GetInt(2), *row);
|
||||
return 0;
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(Matrix3, GetColumn)
|
||||
_GetSelf(Matrix3, Matrix3);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->GetColumn(sa.GetInt(2))));
|
||||
_END_IMPL
|
||||
_MEMBER_FUNCTION_IMPL(Matrix3, SetColumn)
|
||||
_GetSelf(Matrix3, Matrix3);
|
||||
_GetTypedParam(col, 3, Vector4, Vector)
|
||||
self->SetColumn(sa.GetInt(2), *col);
|
||||
return 0;
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix3, _mul)
|
||||
_GetSelf(Matrix3, Matrix3);
|
||||
_GetTypedParam(mtx, 2, Matrix3, Matrix3)
|
||||
_SA_RETURN_OBJECT(new_Matrix3(v, *self * *mtx));
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix3, AsMatrix4)
|
||||
_GetSelf(Matrix3, Matrix3);
|
||||
_SA_RETURN_OBJECT(new_Matrix4(v, Matrix4::FromMatrix3(*self)));
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Matrix3, FromOrthonormalBasis)
|
||||
// _CHECK_SELF(Matrix3, Matrix3);
|
||||
_GetTypedParam(_w, 2, Vector4, Vector)
|
||||
Vector4 *_v = NULL;
|
||||
switch (sa.GetParamCount())
|
||||
{
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
{ _GetTypedParam(__v, 3, Vector4, Vector)
|
||||
_v = __v; } break;
|
||||
default:
|
||||
return sa.ThrowError("Matrix3::FromOrthonormalBasis() wrong parameter count");
|
||||
}
|
||||
_SA_RETURN_OBJECT(new_Matrix3(v, Matrix3::FromOrthonormalBasis(*_w, _v)));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Matrix3, SlerpTo)
|
||||
_GetSelf(Matrix3, Matrix3);
|
||||
_GetTypedParam(to, 3, Matrix3, Matrix3)
|
||||
float t = sa.GetFloat(2);
|
||||
Matrix3 out = Quaternion::Slerp(t, Quaternion::FromMatrix3(*self), Quaternion::FromMatrix3(*to)).AsMatrix3();
|
||||
_SA_RETURN_OBJECT(new_Matrix3(v, out))
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Matrix3, AsEuler)
|
||||
_GetSelf(Matrix3, Matrix3);
|
||||
Math::rOrder rorder = Math::rOrder_Default;
|
||||
if (sa.GetParamCount() == 2)
|
||||
rorder = (Math::rOrder)sa.GetInt(2);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->AsEuler(rorder)));
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/*#
|
||||
Section: Matrix3Generic
|
||||
Desc: Matrix 3x3
|
||||
#*/
|
||||
_BEGIN_CLASS(Matrix3)
|
||||
_MEMBER_FUNCTION(Matrix3, constructor, -1, _T(". n|x n|x n|x nnn nnn"))
|
||||
_MEMBER_FUNCTION(Matrix3, _get, 2, _T("xs"))
|
||||
_MEMBER_FUNCTION(Matrix3, _set, 3, _T("xsn"))
|
||||
_MEMBER_FUNCTION(Matrix3, _mul, 2, _T("xx"))
|
||||
/*#
|
||||
Func: GetRow
|
||||
Proto: Vector:int index
|
||||
Desc: Return a matrix row as a vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix3, GetRow, 2, _T("xi"))
|
||||
/*#
|
||||
Func: SetRow
|
||||
Proto: void:int index, Vector row
|
||||
Desc: Set a matrix row from a vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix3, SetRow, 3, _T("xix"))
|
||||
/*#
|
||||
Func: GetColumn
|
||||
Proto: Vector:int index
|
||||
Desc: Return a matrix column as a vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix3, GetColumn, 2, _T("xi"))
|
||||
/*#
|
||||
Func: SetColumn
|
||||
Proto: void:int index, Vector column
|
||||
Desc: Set a matrix column from a vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix3, SetColumn, 3, _T("xix"))
|
||||
/*#
|
||||
Func: AsMatrix4
|
||||
Proto: Matrix4:
|
||||
Desc: Return matrix as a 4x4 matrix.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix3, AsMatrix4, 1, _T("x"))
|
||||
/*#
|
||||
Func: FromOrthonormalBasis
|
||||
Proto: Matrix3:Vector u,[Vector v]
|
||||
Desc: Build an orientation matrix from one or two basis vectors.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix3, FromOrthonormalBasis, -2, _T(".xx"))
|
||||
/*#
|
||||
Func: SlerpTo
|
||||
Proto: Matrix3:float t,Matrix3 to
|
||||
Desc: Interpolate a 3x3 orientation matrix to another 3x3 orientation matrix using spherical linear interpolation.
|
||||
Example:
|
||||
local m_a = ItemGetRotationMatrix(item_a)
|
||||
local m_b = ItemGetRotationMatrix(item_b)
|
||||
|
||||
// m_c will store a rotation halfway between the rotation stored in the m_a and m_b matrices.
|
||||
local m_c = m_a.SlerpTo(0.5, m_b)
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix3, SlerpTo, 3, _T("xnx"))
|
||||
/*#
|
||||
Func: AsEuler
|
||||
Proto: Vector:[RotationOrder method]
|
||||
Desc: Return a 3x3 orientation matrix as an Euler triplet.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Matrix3, AsEuler, -1, _T("xi"))
|
||||
_END_CLASS(Matrix3)
|
||||
328
include/modules/script_squirrel/cobject/quaternion_impl.cpp
Normal file
328
include/modules/script_squirrel/cobject/quaternion_impl.cpp
Normal file
@ -0,0 +1,328 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
nEngine - GSFramework
|
||||
Copyright 2001-2012 Emmanuel Julien. All Rights Reserved.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
#include "script_squirrel/cobject/quaternion_decl.h"
|
||||
#include "script_squirrel/cobject/matrix_decl.h"
|
||||
#include "script_squirrel/cobject/vector_decl.h"
|
||||
#include "math/matrix3.h"
|
||||
#include "math/quaternion.h"
|
||||
#include "math/vector.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
_DECL_CLASS(Quaternion)
|
||||
_IMPL_NATIVE_CONSTRUCTION(Quaternion, Quaternion)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, constructor)
|
||||
Quaternion temp;
|
||||
int nparams = sa.GetParamCount();
|
||||
|
||||
switch (nparams)
|
||||
{
|
||||
case 1: temp.Set(); break;
|
||||
case 5:
|
||||
temp.Set(sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4), sa.GetFloat(5));
|
||||
break;
|
||||
|
||||
default:
|
||||
return sa.ThrowError("Quaternion() wrong parameter count");
|
||||
}
|
||||
return construct_Quaternion(v, new Quaternion(temp));
|
||||
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, _cloned)
|
||||
_GetTypedParam(quat, 2, Quaternion, Quaternion);
|
||||
return construct_Quaternion(v, new Quaternion(*quat));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, _set)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
|
||||
const SQChar *s = sa.GetString(2);
|
||||
int index = s ? s[0] : sa.GetInt(2);
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0: case 'x':
|
||||
return sa.Return(self->x = sa.GetFloat(3));
|
||||
case 1: case 'y':
|
||||
return sa.Return(self->y = sa.GetFloat(3));
|
||||
case 2: case 'z':
|
||||
return sa.Return(self->z = sa.GetFloat(3));
|
||||
case 3: case 'w':
|
||||
return sa.Return(self->w = sa.GetFloat(3));
|
||||
}
|
||||
return SQ_ERROR;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, _get)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
const SQChar *s = sa.GetString(2);
|
||||
if (s && (s[1] != 0))
|
||||
return SQ_ERROR;
|
||||
int index = s && (s[1] == 0) ? s[0] : sa.GetInt(2);
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0: case 'x':
|
||||
return sa.Return(self->x);
|
||||
case 1: case 'y':
|
||||
return sa.Return(self->y);
|
||||
case 2: case 'z':
|
||||
return sa.Return(self->z);
|
||||
case 3: case 'w':
|
||||
return sa.Return(self->w);
|
||||
}
|
||||
return SQ_ERROR;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, _mul)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
case OT_INSTANCE:
|
||||
{
|
||||
// Quaternion * Quaternion.
|
||||
_CHECK_INST_PARAM_RAW(quat, 2, Quaternion, Quaternion);
|
||||
if (quat)
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, *self * *quat));
|
||||
}
|
||||
break;
|
||||
|
||||
// Quaternion * Scalar
|
||||
case OT_INTEGER:
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, *self * (float)sa.GetInt(2)));
|
||||
case OT_FLOAT:
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, *self * sa.GetFloat(2)));
|
||||
}
|
||||
return sa.ThrowError("Quaternion * operator: Invalid argument type.\n");
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, _div)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
// Quaternion / Scalar
|
||||
case OT_INTEGER:
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, *self / (float)sa.GetInt(2)));
|
||||
case OT_FLOAT:
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, *self / sa.GetFloat(2)));
|
||||
}
|
||||
return sa.ThrowError("Quaternion / operator: Invalid argument type.\n");
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, _add)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
case OT_INSTANCE:
|
||||
{
|
||||
// Quaternion + Quaternion.
|
||||
_CHECK_INST_PARAM_RAW(quat, 2, Quaternion, Quaternion);
|
||||
if (quat)
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, *self + *quat));
|
||||
}
|
||||
break;
|
||||
|
||||
// Quaternion + Scalar
|
||||
case OT_INTEGER:
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, *self + (float)sa.GetInt(2)));
|
||||
case OT_FLOAT:
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, *self + sa.GetFloat(2)));
|
||||
}
|
||||
return sa.ThrowError("Quaternion + operator: Invalid argument type.\n");
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, _sub)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
case OT_INSTANCE:
|
||||
{
|
||||
// Quaternion - Quaternion.
|
||||
_CHECK_INST_PARAM_RAW(quat, 2, Quaternion, Quaternion);
|
||||
if (quat)
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, *self - *quat));
|
||||
}
|
||||
break;
|
||||
|
||||
// Quaternion - Scalar
|
||||
case OT_INTEGER:
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, *self - (float)sa.GetInt(2)));
|
||||
case OT_FLOAT:
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, *self - sa.GetFloat(2)));
|
||||
}
|
||||
return sa.ThrowError("Quaternion - operator: Invalid argument type.\n");
|
||||
_END_IMPL
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, Set)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
switch (sa.GetParamCount())
|
||||
{
|
||||
case 1: self->Set(); break;
|
||||
case 2: self->Set(sa.GetFloat(2)); break;
|
||||
case 3: self->Set(sa.GetFloat(2), sa.GetFloat(3)); break;
|
||||
case 4: self->Set(sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4)); break;
|
||||
case 5: self->Set(sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4), sa.GetFloat(5)); break;
|
||||
default:
|
||||
return sa.ThrowError("Quaternion Set() wrong parameters");
|
||||
}
|
||||
return 0;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, Slerp)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
float k = sa.GetFloat(2);
|
||||
_GetTypedParam(quat, 3, Quaternion, Quaternion)
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, Quaternion::Slerp(k, *self, *quat)));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, Normalize)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, self->Normalize()));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, Inverse)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, self->Inverse()));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, Dot)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
_GetTypedParam(quat, 2, Quaternion, Quaternion);
|
||||
return sa.Return(self->Dot(*quat));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, AsMatrix3)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
_SA_RETURN_OBJECT(new_Matrix3(v, self->AsMatrix3()));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, QuaternionFromAxisAngle)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
_GetTypedParam(vec, 3, Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, Quaternion::FromAxisAngle(sa.GetFloat(2), vec->x, vec->y, vec->z)));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, QuaternionFromMatrix3)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
_GetTypedParam(mtx, 2, Matrix3, Matrix3);
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, Quaternion::FromMatrix3(*mtx)));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, QuaternionLookAt)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
_GetTypedParam(vec, 2, Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Quaternion(v, Quaternion::LookAt(*vec)));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Quaternion, Print)
|
||||
_GetSelf(Quaternion, Quaternion);
|
||||
const char *label = "Quaternion";
|
||||
if (sa.GetParamCount() == 2)
|
||||
label = sa.GetString(2);
|
||||
__LOG__ << label << ": { x = " << self->x << ", y = " << self->y << ", z = " << self->z << ", w = " << self->w << "}\n";
|
||||
return 0;
|
||||
_END_IMPL
|
||||
|
||||
/*#
|
||||
Topic: Quaternion
|
||||
Type: Quaternion
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: QuaternionGeneric
|
||||
Desc: Generic
|
||||
#*/
|
||||
_BEGIN_CLASS(Quaternion)
|
||||
|
||||
/*#
|
||||
Func: Quaternion
|
||||
Proto: Quaternion:float x = 0,float y = 0,float z = 0,float w = 1
|
||||
Desc: Create a new quaternion.
|
||||
Example:
|
||||
local u = Quaternion()
|
||||
local v = Quaternion(0, 0, 0, 1)
|
||||
|
||||
u.Set(-1, 0, 0)
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Quaternion, constructor, -1, _T(".n|xnnn"))
|
||||
_MEMBER_FUNCTION(Quaternion, _cloned, 2, _T(".x"))
|
||||
_MEMBER_FUNCTION(Quaternion, _set, 2, _T("xs|n"))
|
||||
_MEMBER_FUNCTION(Quaternion, _get, 2, _T("xs|n"))
|
||||
_MEMBER_FUNCTION(Quaternion, _add, 2, _T("xx|n"))
|
||||
_MEMBER_FUNCTION(Quaternion, _sub, 2, _T("xx|n"))
|
||||
_MEMBER_FUNCTION(Quaternion, _mul, 2, _T("xx|n"))
|
||||
_MEMBER_FUNCTION(Quaternion, _div, 2, _T("xn"))
|
||||
|
||||
/*#
|
||||
Func: Set
|
||||
Proto: void:float x = 0,float y = 0,float z = 0,float w = 1
|
||||
Desc: Set quaternion values.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Quaternion, Set, -1, _T("xnnnn"))
|
||||
/*#
|
||||
Func: Slerp
|
||||
Proto: Quaternion:float,Quaternion
|
||||
Desc: Returns a spherical linear interpolation.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Quaternion, Slerp, 3, _T("xnx"))
|
||||
/*#
|
||||
Func: Normalize
|
||||
Proto: Quaternion:void
|
||||
Desc: Returns the normalized quaternion.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Quaternion, Normalize, 1, _T("x"))
|
||||
/*#
|
||||
Func: Inverse
|
||||
Proto: Quaternion:void
|
||||
Desc: Returns the inverse quaternion.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Quaternion, Inverse, 1, _T("x"))
|
||||
/*#
|
||||
Func: Dot
|
||||
Proto: Quaternion:Quaternion
|
||||
Desc: Returns the Dot product.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Quaternion, Dot, 2, _T("xx"))
|
||||
/*#
|
||||
Func: AsMatrix3
|
||||
Proto: Matrix3:void
|
||||
Desc: Returns the Matrix3 from the quaternion.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Quaternion, AsMatrix3, 1, _T("x"))
|
||||
/*#
|
||||
Func: QuaternionFromAxisAngle
|
||||
Proto: Quaternion:float angle,Vector axis
|
||||
Desc: Returns a quaternion based on angle and axis.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Quaternion, QuaternionFromAxisAngle, 3, _T(".nx"))
|
||||
/*#
|
||||
Func: QuaternionFromMatrix3
|
||||
Proto: Quaternion:Matrix3
|
||||
Desc: Returns a quaternion based on a Matrix3.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Quaternion, QuaternionFromMatrix3, 2, _T(".x"))
|
||||
/*#
|
||||
Func: QuaternionLookAt
|
||||
Proto: Quaternion:Vector direction
|
||||
Desc: Returns a quaternion looking at direction.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Quaternion, QuaternionLookAt, 2, _T(".x"))
|
||||
/*#
|
||||
Func: Print
|
||||
Proto: void:
|
||||
Desc: Dump this quaternion components (x,y,z,w) to the engine log.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Quaternion, Print, -1, _T("x"))
|
||||
|
||||
_END_CLASS(Quaternion)
|
||||
@ -0,0 +1,113 @@
|
||||
#include "squirrel.h"
|
||||
#include "script_squirrel/cobject/squirrel_object.h"
|
||||
#include "script_squirrel/cobject/squirrel_bindings_utils.h"
|
||||
|
||||
bool CreateStaticNamespace(HSQUIRRELVM v,ScriptNamespaceDecl *sn)
|
||||
{
|
||||
int n = 0;
|
||||
sq_pushroottable(v);
|
||||
sq_pushstring(v,sn->name,-1);
|
||||
sq_newtable(v);
|
||||
const ScriptClassMemberDecl *members = sn->members;
|
||||
const ScriptClassMemberDecl *m = 0;
|
||||
while(members[n].name) {
|
||||
m = &members[n];
|
||||
sq_pushstring(v,m->name,-1);
|
||||
sq_newclosure(v,m->func,0);
|
||||
sq_setparamscheck(v,m->params,m->typemask);
|
||||
sq_setnativeclosurename(v,-1,m->name);
|
||||
sq_createslot(v,-3);
|
||||
n++;
|
||||
}
|
||||
const ScriptConstantDecl *consts = sn->constants;
|
||||
const ScriptConstantDecl *c = 0;
|
||||
n = 0;
|
||||
while(consts[n].name) {
|
||||
c = &consts[n];
|
||||
sq_pushstring(v,c->name,-1);
|
||||
switch(c->type) {
|
||||
case OT_STRING: sq_pushstring(v,c->val.s,-1);break;
|
||||
case OT_INTEGER: sq_pushinteger(v,c->val.i);break;
|
||||
case OT_FLOAT: sq_pushfloat(v,c->val.f);break;
|
||||
}
|
||||
sq_createslot(v,-3);
|
||||
n++;
|
||||
}
|
||||
if(sn->delegate) {
|
||||
const ScriptClassMemberDecl *members = sn->delegate;
|
||||
const ScriptClassMemberDecl *m = 0;
|
||||
sq_newtable(v);
|
||||
while(members[n].name) {
|
||||
m = &members[n];
|
||||
sq_pushstring(v,m->name,-1);
|
||||
sq_newclosure(v,m->func,0);
|
||||
sq_setparamscheck(v,m->params,m->typemask);
|
||||
sq_setnativeclosurename(v,-1,m->name);
|
||||
sq_createslot(v,-3);
|
||||
n++;
|
||||
}
|
||||
sq_setdelegate(v,-2);
|
||||
}
|
||||
sq_createslot(v,-3);
|
||||
sq_pop(v,1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CreateClass(HSQUIRRELVM v,SquirrelClassDecl *cd)
|
||||
{
|
||||
int n = 0;
|
||||
int oldtop = sq_gettop(v);
|
||||
sq_pushroottable(v);
|
||||
sq_pushstring(v,cd->name,-1);
|
||||
if(cd->base) {
|
||||
sq_pushstring(v,cd->base,-1);
|
||||
if(SQ_FAILED(sq_get(v,-3))) {
|
||||
sq_settop(v,oldtop);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(SQ_FAILED(sq_newclass(v,cd->base?1:0))) {
|
||||
sq_settop(v,oldtop);
|
||||
return false;
|
||||
}
|
||||
sq_settypetag(v,-1,(SQUserPointer)cd);
|
||||
const ScriptClassMemberDecl *members = cd->members;
|
||||
const ScriptClassMemberDecl *m = 0;
|
||||
while(members[n].name) {
|
||||
m = &members[n];
|
||||
sq_pushstring(v,m->name,-1);
|
||||
sq_newclosure(v,m->func,0);
|
||||
sq_setparamscheck(v,m->params,m->typemask);
|
||||
sq_setnativeclosurename(v,-1,m->name);
|
||||
sq_createslot(v,-3);
|
||||
n++;
|
||||
}
|
||||
sq_createslot(v,-3);
|
||||
sq_pop(v,1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CreateNativeClassInstance(HSQUIRRELVM v,const SQChar *classname,SQUserPointer ud,SQRELEASEHOOK hook)
|
||||
{
|
||||
int oldtop = sq_gettop(v);
|
||||
sq_pushroottable(v);
|
||||
sq_pushstring(v,classname,-1);
|
||||
if(SQ_FAILED(sq_rawget(v,-2))){
|
||||
sq_settop(v,oldtop);
|
||||
return false;
|
||||
}
|
||||
//sq_pushroottable(v);
|
||||
if(SQ_FAILED(sq_createinstance(v,-1))) {
|
||||
sq_settop(v,oldtop);
|
||||
return false;
|
||||
}
|
||||
sq_remove(v,-3); //removes the root table
|
||||
sq_remove(v,-2); //removes the the class
|
||||
if(SQ_FAILED(sq_setinstanceup(v,-1,ud))) {
|
||||
sq_settop(v,oldtop);
|
||||
return false;
|
||||
}
|
||||
sq_setreleasehook(v,-1,hook);
|
||||
return true;
|
||||
}
|
||||
470
include/modules/script_squirrel/cobject/squirrel_object.cpp
Normal file
470
include/modules/script_squirrel/cobject/squirrel_object.cpp
Normal file
@ -0,0 +1,470 @@
|
||||
#include "squirrel.h"
|
||||
#include "squirrel_object.h"
|
||||
//#include "SquirrelVM.h"
|
||||
|
||||
SquirrelObject::SquirrelObject(HSQUIRRELVM v)
|
||||
{
|
||||
vm = v;
|
||||
sq_resetobject(&_o);
|
||||
}
|
||||
|
||||
SquirrelObject::~SquirrelObject()
|
||||
{
|
||||
if(vm)
|
||||
sq_release(vm,&_o);
|
||||
}
|
||||
|
||||
SquirrelObject::SquirrelObject(const SquirrelObject &o)
|
||||
{
|
||||
vm = o.vm;
|
||||
_o = o._o;
|
||||
sq_addref(vm,&_o);
|
||||
}
|
||||
|
||||
SquirrelObject::SquirrelObject(HSQOBJECT &o)
|
||||
{
|
||||
_o = o;
|
||||
sq_addref(vm,&_o);
|
||||
}
|
||||
|
||||
SquirrelObject SquirrelObject::Clone()
|
||||
{
|
||||
SquirrelObject ret(vm);
|
||||
if(GetType() == OT_TABLE || GetType() == OT_ARRAY)
|
||||
{
|
||||
sq_pushobject(vm,_o);
|
||||
sq_clone(vm,-1);
|
||||
ret.AttachToStackObject(-1);
|
||||
sq_pop(vm,2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SquirrelObject & SquirrelObject::operator =(const SquirrelObject &o)
|
||||
{
|
||||
HSQOBJECT t;
|
||||
t = o._o;
|
||||
sq_addref(vm,&t);
|
||||
sq_release(vm,&_o);
|
||||
_o = t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SquirrelObject & SquirrelObject::operator =(int n)
|
||||
{
|
||||
sq_pushinteger(vm,n);
|
||||
AttachToStackObject(-1);
|
||||
sq_pop(vm,1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SquirrelObject::Append(const SquirrelObject &o)
|
||||
{
|
||||
if(sq_isarray(_o)) {
|
||||
sq_pushobject(vm,_o);
|
||||
sq_pushobject(vm,o._o);
|
||||
sq_arrayappend(vm,-2);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
}
|
||||
|
||||
void SquirrelObject::AttachToStackObject(int idx)
|
||||
{
|
||||
HSQOBJECT t;
|
||||
sq_getstackobj(vm,idx,&t);
|
||||
sq_addref(vm,&t);
|
||||
sq_release(vm,&_o);
|
||||
_o = t;
|
||||
}
|
||||
|
||||
bool SquirrelObject::SetDelegate(SquirrelObject &obj)
|
||||
{
|
||||
if(obj.GetType() == OT_TABLE ||
|
||||
obj.GetType() == OT_NULL) {
|
||||
switch(_o._type) {
|
||||
case OT_USERDATA:
|
||||
case OT_TABLE:
|
||||
sq_pushobject(vm,_o);
|
||||
sq_pushobject(vm,obj._o);
|
||||
if(SQ_SUCCEEDED(sq_setdelegate(vm,-2)))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SquirrelObject SquirrelObject::GetDelegate()
|
||||
{
|
||||
SquirrelObject ret(vm);
|
||||
if(_o._type == OT_TABLE || _o._type == OT_USERDATA)
|
||||
{
|
||||
sq_pushobject(vm,_o);
|
||||
sq_getdelegate(vm,-1);
|
||||
ret.AttachToStackObject(-1);
|
||||
sq_pop(vm,2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SquirrelObject::IsNull() const
|
||||
{
|
||||
return sq_isnull(_o);
|
||||
}
|
||||
|
||||
bool SquirrelObject::IsNumeric() const
|
||||
{
|
||||
return sq_isnumeric(_o) ? true : false;
|
||||
}
|
||||
|
||||
int SquirrelObject::Len() const
|
||||
{
|
||||
int ret = 0;
|
||||
if(sq_isarray(_o) || sq_istable(_o) || sq_isstring(_o)) {
|
||||
sq_pushobject(vm,_o);
|
||||
ret = sq_getsize(vm,-1);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define _SETVALUE_INT_BEGIN \
|
||||
bool ret = false; \
|
||||
int top = sq_gettop(vm); \
|
||||
sq_pushobject(vm,_o); \
|
||||
sq_pushinteger(vm,key);
|
||||
|
||||
#define _SETVALUE_INT_END \
|
||||
if(SQ_SUCCEEDED(sq_rawset(vm,-3))) { \
|
||||
ret = true; \
|
||||
} \
|
||||
sq_settop(vm,top); \
|
||||
return ret;
|
||||
|
||||
bool SquirrelObject::SetValue(SQInteger key,const SquirrelObject &val)
|
||||
{
|
||||
_SETVALUE_INT_BEGIN
|
||||
sq_pushobject(vm,val._o);
|
||||
_SETVALUE_INT_END
|
||||
}
|
||||
|
||||
bool SquirrelObject::SetValue(int key,int n)
|
||||
{
|
||||
_SETVALUE_INT_BEGIN
|
||||
sq_pushinteger(vm,n);
|
||||
_SETVALUE_INT_END
|
||||
}
|
||||
|
||||
bool SquirrelObject::SetValue(int key,float f)
|
||||
{
|
||||
_SETVALUE_INT_BEGIN
|
||||
sq_pushfloat(vm,f);
|
||||
_SETVALUE_INT_END
|
||||
}
|
||||
|
||||
bool SquirrelObject::SetValue(int key,const SQChar *s)
|
||||
{
|
||||
_SETVALUE_INT_BEGIN
|
||||
sq_pushstring(vm,s,-1);
|
||||
_SETVALUE_INT_END
|
||||
}
|
||||
|
||||
bool SquirrelObject::SetValue(int key,bool b)
|
||||
{
|
||||
_SETVALUE_INT_BEGIN
|
||||
sq_pushbool(vm,b);
|
||||
_SETVALUE_INT_END
|
||||
}
|
||||
|
||||
bool SquirrelObject::SetValue(const SquirrelObject &key,const SquirrelObject &val)
|
||||
{
|
||||
bool ret = false;
|
||||
int top = sq_gettop(vm);
|
||||
sq_pushobject(vm,_o);
|
||||
sq_pushobject(vm,key._o);
|
||||
sq_pushobject(vm,val._o);
|
||||
if(SQ_SUCCEEDED(sq_rawset(vm,-3))) {
|
||||
ret = true;
|
||||
}
|
||||
sq_settop(vm,top);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define _SETVALUE_STR_BEGIN \
|
||||
bool ret = false; \
|
||||
int top = sq_gettop(vm); \
|
||||
sq_pushobject(vm,_o); \
|
||||
sq_pushstring(vm,key,-1);
|
||||
|
||||
#define _SETVALUE_STR_END \
|
||||
if(SQ_SUCCEEDED(sq_rawset(vm,-3))) { \
|
||||
ret = true; \
|
||||
} \
|
||||
sq_settop(vm,top); \
|
||||
return ret;
|
||||
|
||||
bool SquirrelObject::SetValue(const SQChar *key,const SquirrelObject &val)
|
||||
{
|
||||
_SETVALUE_STR_BEGIN
|
||||
sq_pushobject(vm,val._o);
|
||||
_SETVALUE_STR_END
|
||||
}
|
||||
|
||||
bool SquirrelObject::SetValue(const SQChar *key,int n)
|
||||
{
|
||||
_SETVALUE_STR_BEGIN
|
||||
sq_pushinteger(vm,n);
|
||||
_SETVALUE_STR_END
|
||||
}
|
||||
|
||||
bool SquirrelObject::SetValue(const SQChar *key,float f)
|
||||
{
|
||||
_SETVALUE_STR_BEGIN
|
||||
sq_pushfloat(vm,f);
|
||||
_SETVALUE_STR_END
|
||||
}
|
||||
|
||||
bool SquirrelObject::SetValue(const SQChar *key,const SQChar *s)
|
||||
{
|
||||
_SETVALUE_STR_BEGIN
|
||||
sq_pushstring(vm,s,-1);
|
||||
_SETVALUE_STR_END
|
||||
}
|
||||
|
||||
bool SquirrelObject::SetValue(const SQChar *key,bool b)
|
||||
{
|
||||
_SETVALUE_STR_BEGIN
|
||||
sq_pushbool(vm,b);
|
||||
_SETVALUE_STR_END
|
||||
}
|
||||
|
||||
|
||||
SQObjectType SquirrelObject::GetType()
|
||||
{
|
||||
return _o._type;
|
||||
}
|
||||
|
||||
bool SquirrelObject::GetSlot(int key) const
|
||||
{
|
||||
sq_pushobject(vm,_o);
|
||||
sq_pushinteger(vm,key);
|
||||
if(SQ_SUCCEEDED(sq_get(vm,-2))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
SquirrelObject SquirrelObject::GetValue(int key)const
|
||||
{
|
||||
SquirrelObject ret(vm);
|
||||
if(GetSlot(key)) {
|
||||
ret.AttachToStackObject(-1);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
sq_pop(vm,1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
float SquirrelObject::GetFloat(int key) const
|
||||
{
|
||||
float ret = 0.0f;
|
||||
if(GetSlot(key)) {
|
||||
sq_getfloat(vm,-1,&ret);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
sq_pop(vm,1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SquirrelObject::GetInt(int key) const
|
||||
{
|
||||
SQInteger ret = 0;
|
||||
if(GetSlot(key)) {
|
||||
sq_getinteger(vm,-1,&ret);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
sq_pop(vm,1);
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
const SQChar *SquirrelObject::GetString(int key) const
|
||||
{
|
||||
const SQChar *ret = 0;
|
||||
if(GetSlot(key)) {
|
||||
sq_getstring(vm,-1,&ret);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
sq_pop(vm,1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SquirrelObject::GetBool(int key) const
|
||||
{
|
||||
SQBool ret = false;
|
||||
if(GetSlot(key)) {
|
||||
sq_getbool(vm,-1,&ret);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
sq_pop(vm,1);
|
||||
return ret?true:false;
|
||||
}
|
||||
|
||||
bool SquirrelObject::Exists(const SQChar *key) const
|
||||
{
|
||||
bool ret = false;
|
||||
if(GetSlot(key)) {
|
||||
ret = true;
|
||||
}
|
||||
sq_pop(vm,1);
|
||||
return ret;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool SquirrelObject::GetSlot(const SQChar *name) const
|
||||
{
|
||||
sq_pushobject(vm,_o);
|
||||
sq_pushstring(vm,name,-1);
|
||||
if(SQ_SUCCEEDED(sq_get(vm,-2))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SquirrelObject SquirrelObject::GetValue(const SQChar *key)const
|
||||
{
|
||||
SquirrelObject ret(vm);
|
||||
if(GetSlot(key)) {
|
||||
ret.AttachToStackObject(-1);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
sq_pop(vm,1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
float SquirrelObject::GetFloat(const SQChar *key) const
|
||||
{
|
||||
float ret = 0.0f;
|
||||
if(GetSlot(key)) {
|
||||
sq_getfloat(vm,-1,&ret);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
sq_pop(vm,1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SquirrelObject::GetInt(const SQChar *key) const
|
||||
{
|
||||
SQInteger ret = 0;
|
||||
if(GetSlot(key)) {
|
||||
sq_getinteger(vm,-1,&ret);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
sq_pop(vm,1);
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
const SQChar *SquirrelObject::GetString(const SQChar *key) const
|
||||
{
|
||||
const SQChar *ret = 0;
|
||||
if(GetSlot(key)) {
|
||||
sq_getstring(vm,-1,&ret);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
sq_pop(vm,1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SquirrelObject::GetBool(const SQChar *key) const
|
||||
{
|
||||
SQBool ret = false;
|
||||
if(GetSlot(key)) {
|
||||
sq_getbool(vm,-1,&ret);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
sq_pop(vm,1);
|
||||
return ret?true:false;
|
||||
}
|
||||
|
||||
SQUserPointer SquirrelObject::GetInstanceUP(SQUserPointer tag) const
|
||||
{
|
||||
SQUserPointer up = 0;
|
||||
sq_pushobject(vm,_o);
|
||||
sq_getinstanceup(vm,-1,(SQUserPointer*)&up,(SQUserPointer)tag);
|
||||
sq_pop(vm,1);
|
||||
return up;
|
||||
}
|
||||
|
||||
bool SquirrelObject::SetInstanceUP(SQUserPointer up)
|
||||
{
|
||||
if(!sq_isinstance(_o)) return false;
|
||||
sq_pushobject(vm,_o);
|
||||
sq_setinstanceup(vm,-1,up);
|
||||
sq_pop(vm,1);
|
||||
return true;
|
||||
}
|
||||
|
||||
SquirrelObject SquirrelObject::GetAttributes(const SQChar *key)
|
||||
{
|
||||
SquirrelObject ret(vm);
|
||||
int top = sq_gettop(vm);
|
||||
sq_pushobject(vm,_o);
|
||||
if(key)
|
||||
sq_pushstring(vm,key,-1);
|
||||
else
|
||||
sq_pushnull(vm);
|
||||
if(SQ_SUCCEEDED(sq_getattributes(vm,-2))) {
|
||||
ret.AttachToStackObject(-1);
|
||||
}
|
||||
sq_settop(vm,top);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SquirrelObject::BeginIteration()
|
||||
{
|
||||
if(!sq_istable(_o) && !sq_isarray(_o) && !sq_isclass(_o))
|
||||
return false;
|
||||
sq_pushobject(vm,_o);
|
||||
sq_pushnull(vm);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SquirrelObject::Next(SquirrelObject &key,SquirrelObject &val)
|
||||
{
|
||||
if(SQ_SUCCEEDED(sq_next(vm,-2))) {
|
||||
key.AttachToStackObject(-2);
|
||||
val.AttachToStackObject(-1);
|
||||
sq_pop(vm,2);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const SQChar* SquirrelObject::ToString()
|
||||
{
|
||||
return sq_objtostring(&_o);
|
||||
}
|
||||
|
||||
SQInteger SquirrelObject::ToInteger()
|
||||
{
|
||||
return sq_objtointeger(&_o);
|
||||
}
|
||||
|
||||
SQFloat SquirrelObject::ToFloat()
|
||||
{
|
||||
return sq_objtofloat(&_o);
|
||||
}
|
||||
|
||||
bool SquirrelObject::ToBool()
|
||||
{
|
||||
//<<FIXME>>
|
||||
return _o._unVal.nInteger?true:false;
|
||||
}
|
||||
|
||||
void SquirrelObject::EndIteration()
|
||||
{
|
||||
sq_pop(vm,2);
|
||||
}
|
||||
29
include/modules/script_squirrel/cobject/uc_binding.cpp
Normal file
29
include/modules/script_squirrel/cobject/uc_binding.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "script_squirrel/cobject/geometry_template_decl.h"
|
||||
#include "script_squirrel/cobject/cobject_decl.h"
|
||||
#include "script_squirrel/cobject/matrix_decl.h"
|
||||
#include "script_squirrel/cobject/vector_decl.h"
|
||||
#include "script_squirrel/cobject/uv_decl.h"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterUCBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
// Engine types wrapper object.
|
||||
_INIT_CLASS(vm, CObject)
|
||||
|
||||
// VM owned objects.
|
||||
_INIT_CLASS(vm, GeometryTemplate)
|
||||
|
||||
_INIT_CLASS(vm, Matrix3)
|
||||
_INIT_CLASS(vm, Matrix4)
|
||||
_INIT_CLASS(vm, Vector)
|
||||
|
||||
_INIT_CLASS(vm, UV)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
122
include/modules/script_squirrel/cobject/uv_impl.cpp
Normal file
122
include/modules/script_squirrel/cobject/uv_impl.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "script_squirrel/cobject/uv_decl.h"
|
||||
#include "script_squirrel/cobject/vector_decl.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
#ifndef _T
|
||||
#define _T
|
||||
#endif
|
||||
|
||||
|
||||
_IMPL_NATIVE_CONSTRUCTION(UV, GS::Vector2);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(UV, constructor)
|
||||
Vector2 temp;
|
||||
int nparams = sa.GetParamCount();
|
||||
|
||||
switch (nparams)
|
||||
{
|
||||
case 1: temp.Set(0, 0); break;
|
||||
case 2:
|
||||
if (sa.GetType(2) == OT_INSTANCE)
|
||||
{
|
||||
_GetTypedParam(uv, 2, Vector2, UV);
|
||||
if (uv)
|
||||
temp = *uv;
|
||||
else return sa.ThrowError("Invalid instance type");
|
||||
}
|
||||
else temp.Set(sa.GetFloat(2), 0);
|
||||
break;
|
||||
case 3: temp.Set(sa.GetFloat(2), sa.GetFloat(3)); break;
|
||||
|
||||
default:
|
||||
return sa.ThrowError("Wrong parameter count");
|
||||
}
|
||||
return construct_UV(v, new Vector2(temp));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(UV, _cloned)
|
||||
_GetTypedParam(uv, 2, Vector2, UV);
|
||||
return construct_UV(v, new Vector2(*uv));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(UV, _set)
|
||||
_GetSelf(Vector2, UV);
|
||||
|
||||
const SQChar *s = sa.GetString(2);
|
||||
int index = s ? s[0] : sa.GetInt(2);
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0: case 'u': case 'x':
|
||||
return sa.Return(self->x = sa.GetFloat(3));
|
||||
case 1: case 'v': case 'y':
|
||||
return sa.Return(self->y = sa.GetFloat(3));
|
||||
}
|
||||
return SQ_ERROR;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(UV, _get)
|
||||
_GetSelf(Vector2, UV);
|
||||
const SQChar *s = sa.GetString(2);
|
||||
if (s && (s[1] != 0))
|
||||
return SQ_ERROR;
|
||||
int index = s && (s[1] == 0) ? s[0] : sa.GetInt(2);
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0: case 'u': case 'x':
|
||||
return sa.Return(self->x);
|
||||
case 1: case 'v': case 'y':
|
||||
return sa.Return(self->y);
|
||||
}
|
||||
return SQ_ERROR;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(UV, Set)
|
||||
_GetSelf(Vector2, UV);
|
||||
switch (sa.GetParamCount())
|
||||
{
|
||||
case 1: self->Set(0, 0); break;
|
||||
case 2: self->Set(sa.GetFloat(2), 0); break;
|
||||
case 3: self->Set(sa.GetFloat(2), sa.GetFloat(3)); break;
|
||||
default:
|
||||
return sa.ThrowError("Wrong parameter count");
|
||||
}
|
||||
return 0;
|
||||
_END_IMPL
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/*#
|
||||
Topic: UV
|
||||
Type: UV
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: UVGeneric
|
||||
Desc: Generic
|
||||
#*/
|
||||
_BEGIN_CLASS(UV)
|
||||
|
||||
_MEMBER_FUNCTION(UV, constructor, -1, _T(".n|xn"))
|
||||
_MEMBER_FUNCTION(UV, _cloned, 2, _T(".x"))
|
||||
_MEMBER_FUNCTION(UV, _set, 3, _T("xs|n"))
|
||||
_MEMBER_FUNCTION(UV, _get, 2, _T("xs|n"))
|
||||
|
||||
/*#
|
||||
Func: Set
|
||||
Proto: void:float x = 0,float y = 0
|
||||
Desc: Set UV values.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(UV, Set, -1, _T("xnn"))
|
||||
|
||||
_END_CLASS(UV)
|
||||
//------------------------------------------------------------------------------
|
||||
533
include/modules/script_squirrel/cobject/vector_impl.cpp
Normal file
533
include/modules/script_squirrel/cobject/vector_impl.cpp
Normal file
@ -0,0 +1,533 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <cmath>
|
||||
#include "script_squirrel/cobject/vector_decl.h"
|
||||
#include "script_squirrel/cobject/matrix_decl.h"
|
||||
#include "math/matrix4.h"
|
||||
#include "math/matrix3.h"
|
||||
#include "math/vector.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
#ifndef _T
|
||||
#define _T
|
||||
#endif
|
||||
|
||||
_IMPL_NATIVE_CONSTRUCTION(Vector, Vector4);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
_MEMBER_FUNCTION_IMPL(Vector, constructor)
|
||||
Vector4 temp;
|
||||
int nparams = sa.GetParamCount();
|
||||
|
||||
switch (nparams)
|
||||
{
|
||||
case 1: temp.Set(); break;
|
||||
case 2:
|
||||
if (sa.GetType(2) == OT_INSTANCE)
|
||||
{
|
||||
_GetTypedParam(vec, 2, Vector4, Vector);
|
||||
if (vec)
|
||||
temp = *vec;
|
||||
else return sa.ThrowError("Vector() invalid instance type");
|
||||
}
|
||||
else
|
||||
temp.Set(sa.GetFloat(2));
|
||||
break;
|
||||
case 3: temp.Set(sa.GetFloat(2), sa.GetFloat(3)); break;
|
||||
case 4: temp.Set(sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4)); break;
|
||||
case 5: temp.Set(sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4), sa.GetFloat(5)); break;
|
||||
|
||||
default:
|
||||
return sa.ThrowError("Vector wrong parameters");
|
||||
}
|
||||
return construct_Vector(v, new Vector4(temp));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, _cloned)
|
||||
_GetTypedParam(vec, 2, Vector4, Vector);
|
||||
return construct_Vector(v, new Vector4(*vec));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, _set)
|
||||
_GetSelf(Vector4, Vector);
|
||||
|
||||
const SQChar *s = sa.GetString(2);
|
||||
int index = s ? s[0] : sa.GetInt(2);
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0: case 'x': case 'r':
|
||||
return sa.Return(self->x = sa.GetFloat(3));
|
||||
case 1: case 'y': case 'g':
|
||||
return sa.Return(self->y = sa.GetFloat(3));
|
||||
case 2: case 'z': case 'b':
|
||||
return sa.Return(self->z = sa.GetFloat(3));
|
||||
case 3: case 'w': case 'a':
|
||||
return sa.Return(self->w = sa.GetFloat(3));
|
||||
}
|
||||
return SQ_ERROR;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, _get)
|
||||
_GetSelf(Vector4, Vector);
|
||||
const SQChar *s = sa.GetString(2);
|
||||
if (s && (s[1] != 0))
|
||||
return SQ_ERROR;
|
||||
int index = s && (s[1] == 0) ? s[0] : sa.GetInt(2);
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0: case 'x': case 'r':
|
||||
return sa.Return(self->x);
|
||||
case 1: case 'y': case 'g':
|
||||
return sa.Return(self->y);
|
||||
case 2: case 'z': case 'b':
|
||||
return sa.Return(self->z);
|
||||
case 3: case 'w': case 'a':
|
||||
return sa.Return(self->w);
|
||||
}
|
||||
return SQ_ERROR;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, _add)
|
||||
_GetSelf(Vector4, Vector);
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
case OT_INSTANCE:
|
||||
{ _GetTypedParam(vec, 2, Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self + *vec)) }
|
||||
case OT_FLOAT:
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self + sa.GetFloat(2)));
|
||||
}
|
||||
return sa.ThrowError("Vector + operator: Invalid argument type.\n");
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, _sub)
|
||||
_GetSelf(Vector4, Vector);
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
case OT_INSTANCE:
|
||||
{ _GetTypedParam(vec, 2, Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self - *vec)); }
|
||||
case OT_FLOAT:
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self - sa.GetFloat(2)));
|
||||
}
|
||||
return sa.ThrowError("Vector - operator: Invalid argument type.\n");
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, _mul)
|
||||
_GetSelf(Vector4, Vector);
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
case OT_INSTANCE:
|
||||
{
|
||||
// Vector * Vector.
|
||||
_CHECK_INST_PARAM_RAW(vec, 2, Vector4, Vector);
|
||||
if (vec)
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self * *vec));
|
||||
// Vector * Matrix3.
|
||||
_CHECK_INST_PARAM_RAW(m3, 2, Matrix3, Matrix3);
|
||||
if (m3)
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self * *m3));
|
||||
// Vector * Matrix4.
|
||||
_CHECK_INST_PARAM_RAW(m4, 2, Matrix4, Matrix4);
|
||||
if (m4)
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self * *m4));
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_INTEGER:
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self * (float)sa.GetInt(2)));
|
||||
case OT_FLOAT:
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self * sa.GetFloat(2)));
|
||||
}
|
||||
return sa.ThrowError("Vector * operator: Invalid argument type.\n");
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector,_div)
|
||||
_GetSelf(Vector4, Vector);
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
case OT_INSTANCE:
|
||||
{ _GetTypedParam(vec, 2, Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self / *vec)); }
|
||||
case OT_FLOAT:
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self / sa.GetFloat(2)));
|
||||
}
|
||||
return sa.ThrowError("Vector / operator: Invalid argument type.\n");
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Set)
|
||||
_GetSelf(Vector4, Vector);
|
||||
switch (sa.GetParamCount())
|
||||
{
|
||||
case 1: self->Set(); break;
|
||||
case 2: self->Set(sa.GetFloat(2)); break;
|
||||
case 3: self->Set(sa.GetFloat(2), sa.GetFloat(3)); break;
|
||||
case 4: self->Set(sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4)); break;
|
||||
case 5: self->Set(sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4), sa.GetFloat(5)); break;
|
||||
default:
|
||||
return sa.ThrowError("Vector Set() wrong parameters");
|
||||
}
|
||||
return 0;
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Dot)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_GetTypedParam(vec, 2, Vector4, Vector);
|
||||
return sa.Return(self->Dot(*vec));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Cross)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_GetTypedParam(vec, 2, Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->Cross(*vec)));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, AngleWithVector)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_GetTypedParam(vec, 2, Vector4, Vector);
|
||||
return sa.Return(acosf(Types::Clamp(self->Dot(*vec), -1.f, 1.f)));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Reverse)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->Reversed()));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Dist)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_GetTypedParam(vec, 2, Vector4, Vector);
|
||||
return sa.Return(Vector4::Dist(*self, *vec));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Dist2)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_GetTypedParam(vec, 2, Vector4, Vector);
|
||||
return sa.Return(Vector4::Dist2(*self, *vec));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Len)
|
||||
_GetSelf(Vector4, Vector);
|
||||
return sa.Return(self->Len());
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Len2)
|
||||
_GetSelf(Vector4, Vector);
|
||||
return sa.Return(self->Len2());
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, ClampMagnitude)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->ClampedMagnitude(0, sa.GetFloat(2))));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, clamp)
|
||||
_GetSelf(Vector4, Vector);
|
||||
Vector4 mn, mx;
|
||||
if (sa.GetType(2) == OT_INSTANCE)
|
||||
{ _GetTypedParam(_mn, 2, Vector4, Vector); mn = *_mn; }
|
||||
else mn.Set(sa.GetFloat(2), sa.GetFloat(2), sa.GetFloat(2));
|
||||
if (sa.GetType(3) == OT_INSTANCE)
|
||||
{ _GetTypedParam(_mx, 3, Vector4, Vector); mx = *_mx; }
|
||||
else mx.Set(sa.GetFloat(3), sa.GetFloat(3), sa.GetFloat(3));
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->Clamped(mn, mx)));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, ApplyMatrix)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_CHECK_INST_PARAM_RAW(m3, 2, Matrix3, Matrix3);
|
||||
if (m3) _SA_RETURN_OBJECT(new_Vector(v, *self * *m3));
|
||||
_CHECK_INST_PARAM_RAW(m4, 2, Matrix4, Matrix4);
|
||||
if (m4) _SA_RETURN_OBJECT(new_Vector(v, *self * *m4));
|
||||
return sa.ThrowError("Vector::ApplyMatrix(): Invalid parameter");
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, ApplyRotationMatrix)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_CHECK_INST_PARAM_RAW(m3, 2, Matrix3, Matrix3);
|
||||
if (m3) _SA_RETURN_OBJECT(new_Vector(v, *self * *m3));
|
||||
_CHECK_INST_PARAM_RAW(m4, 2, Matrix4, Matrix4);
|
||||
if (m4) _SA_RETURN_OBJECT(new_Vector(v, *self * Matrix3::FromMatrix4(*m4)));
|
||||
return sa.ThrowError("Vector::ApplyRotationMatrix(): Invalid parameter");
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Randomize)
|
||||
if (sa.GetParamCount() == 2)
|
||||
_SA_RETURN_OBJECT(new_Vector(v, Vector4::Random(0, sa.GetFloat(2))));
|
||||
_SA_RETURN_OBJECT(new_Vector(v, Vector4::Random(sa.GetFloat(2), sa.GetFloat(3))));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Normalize)
|
||||
_GetSelf(Vector4, Vector);
|
||||
if (sa.GetParamCount() == 1)
|
||||
_SA_RETURN_OBJECT(new_Vector(v, self->Normalized()))
|
||||
else _SA_RETURN_OBJECT(new_Vector(v, self->Normalized() * sa.GetFloat(2)))
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Lerp)
|
||||
_GetSelf(Vector4, Vector);
|
||||
float k = sa.GetFloat(2), ik = 1.f - k;
|
||||
_GetTypedParam(vec, 3, Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self * k + *vec * ik));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, _cmp)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_GetTypedParam(vec, 2, Vector4, Vector);
|
||||
return sa.Return((*self) == (*vec) ? true : false);
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, IsEqual)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_GetTypedParam(vec, 2, Vector4, Vector);
|
||||
float d2 = 0.0001f;
|
||||
switch (sa.GetParamCount())
|
||||
{
|
||||
case 2: break;
|
||||
case 3: d2 = sa.GetFloat(3); break;
|
||||
default: return sa.ThrowError("Vector::IsEqual() wrong parameter count");
|
||||
}
|
||||
d2 *= d2;
|
||||
return sa.Return(Vector4::Dist2(*self, *vec) < d2 ? true : false);
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Min)
|
||||
_GetSelf(Vector4, Vector);
|
||||
|
||||
if ((sa.GetParamCount() == 2) || (sa.GetParamCount() == 4))
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
case OT_INSTANCE:
|
||||
{ _GetTypedParam(vec, 2, Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, Vector4(self->x < vec->x ? self->x : vec->x, self->y < vec->y ? self->y : vec->y, self->z < vec->z ? self->z : vec->z))); }
|
||||
case OT_FLOAT:
|
||||
{ float x = sa.GetFloat(2), y = sa.GetFloat(3), z = sa.GetFloat(4);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, Vector4(self->x < x ? self->x : x, self->y < y ? self->y : y, self->z < z ? self->z : z))); }
|
||||
}
|
||||
return sa.ThrowError("Vector Min(): Invalid parameter list.\n");
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Max)
|
||||
_GetSelf(Vector4, Vector);
|
||||
if ((sa.GetParamCount() == 2) || (sa.GetParamCount() == 4))
|
||||
switch (sa.GetType(2))
|
||||
{
|
||||
case OT_INSTANCE:
|
||||
{ _GetTypedParam(vec, 2, Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, Vector4(self->x > vec->x ? self->x : vec->x, self->y > vec->y ? self->y : vec->y, self->z > vec->z ? self->z : vec->z))); }
|
||||
case OT_FLOAT:
|
||||
{ float x = sa.GetFloat(2), y = sa.GetFloat(3), z = sa.GetFloat(4);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, Vector4(self->x > x ? self->x : x, self->y > y ? self->y : y, self->z > z ? self->z : z))); }
|
||||
}
|
||||
return sa.ThrowError("Vector Max(): Invalid parameter list.\n");
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Scale)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self * sa.GetFloat(2)));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, AddReal)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self + Vector4(sa.GetFloat(2), sa.GetFloat(2), sa.GetFloat(2))));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, MulReal)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self * Vector4(sa.GetFloat(2), sa.GetFloat(2), sa.GetFloat(2))));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, SubReal)
|
||||
_GetSelf(Vector4, Vector);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self - Vector4(sa.GetFloat(2), sa.GetFloat(2), sa.GetFloat(2))));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, DivReal)
|
||||
_GetSelf(Vector4, Vector);
|
||||
const float ik = 1.f / sa.GetFloat(2);
|
||||
_SA_RETURN_OBJECT(new_Vector(v, *self * Vector4(ik, ik, ik)));
|
||||
_END_IMPL
|
||||
|
||||
_MEMBER_FUNCTION_IMPL(Vector, Print)
|
||||
_GetSelf(Vector4, Vector);
|
||||
const char *label = "Vector";
|
||||
if (sa.GetParamCount() == 2)
|
||||
label = sa.GetString(2);
|
||||
__LOG__ << label << ": { " << self->x << ", " << self->y << ", " << self->z << ", " << self->w << "}\n";
|
||||
return 0;
|
||||
_END_IMPL
|
||||
|
||||
/*#
|
||||
Topic: Vector
|
||||
Type: Vector
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: VectorGeneric
|
||||
Desc: Generic
|
||||
#*/
|
||||
_BEGIN_CLASS(Vector)
|
||||
|
||||
/*#
|
||||
Func: Vector
|
||||
Proto: Vector:float x = 0,float y = 0,float z = 0,float w = 1
|
||||
Desc: Create a new vector.
|
||||
Example: local v = Vector(1, 0, 0)
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, constructor, -1, _T(".n|xnnn"))
|
||||
_MEMBER_FUNCTION(Vector, _cloned, 2, _T(".x"))
|
||||
_MEMBER_FUNCTION(Vector, _set, 3, _T("xs|n"))
|
||||
_MEMBER_FUNCTION(Vector, _get, 2, _T("xs|n"))
|
||||
_MEMBER_FUNCTION(Vector, _add, 2, _T("xx|n"))
|
||||
_MEMBER_FUNCTION(Vector, _sub, 2, _T("xx|n"))
|
||||
_MEMBER_FUNCTION(Vector, _mul, 2, _T("xx|n"))
|
||||
_MEMBER_FUNCTION(Vector, _div, 2, _T("xx|n"))
|
||||
_MEMBER_FUNCTION(Vector, _cmp, 2, _T("xx"))
|
||||
|
||||
/*#
|
||||
Func: Set
|
||||
Proto: void:float x = 0,float y = 0,float z = 0,float w = 1
|
||||
Desc: Set vector values.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Set, -1, _T("xnnnn"))
|
||||
/*#
|
||||
Func: ApplyMatrix
|
||||
Proto: Vector:[Matrix4|Matrix3] matrix
|
||||
Desc: Transform vector by a given matrix.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, ApplyMatrix, 2, _T("xx"))
|
||||
/*#
|
||||
Func: ApplyRotationMatrix
|
||||
Proto: Vector:[Matrix4|Matrix3] matrix
|
||||
Desc: Transform vector by the rotation part of a given matrix.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, ApplyRotationMatrix, 2, _T("xx"))
|
||||
|
||||
_MEMBER_FUNCTION(Vector, AddReal, 2, _T("xn"))
|
||||
_MEMBER_FUNCTION(Vector, MulReal, 2, _T("xn"))
|
||||
_MEMBER_FUNCTION(Vector, SubReal, 2, _T("xn"))
|
||||
_MEMBER_FUNCTION(Vector, DivReal, 2, _T("xn"))
|
||||
_MEMBER_FUNCTION(Vector, Scale, 2, _T("xn"))
|
||||
/*#
|
||||
Func: Clamp
|
||||
Proto: Vector:(Vector|float) min,(Vector|float) max
|
||||
Desc: Individually clamp vector components to a given range.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, clamp, 3, _T("x x|n x|n"))
|
||||
/*#
|
||||
Func: ClampMagnitude
|
||||
Proto: Vector:float len
|
||||
Desc: Clamp vector magnitude to a specific length.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, ClampMagnitude, 2, _T("xn"))
|
||||
/*#
|
||||
Func: Reverse
|
||||
Proto: Vector:
|
||||
Desc: Return the reverse vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Reverse, 1, _T("x"))
|
||||
|
||||
/*#
|
||||
Func: Min
|
||||
Proto: Vector:[Vector|float x,float y, float z] min
|
||||
Desc: Return the smallest value of the vector component or parameter for all the vector components.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Min, -2, _T("xn|xnn"))
|
||||
/*#
|
||||
Func: Max
|
||||
Proto: Vector:[Vector|float x,float y, float z] max
|
||||
Desc: Return the largest value of the vector component or parameter for all the vector components.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Max, -2, _T("xn|xnn"))
|
||||
|
||||
/*#
|
||||
Func: Dot
|
||||
Proto: float:Vector v
|
||||
Desc: Return the dot product between two vectors.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Dot, 2, _T("xx"))
|
||||
/*#
|
||||
Func: Cross
|
||||
Proto: Vector:Vector v
|
||||
Desc: Return the cross product between two vectors.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Cross, 2, _T("xx"))
|
||||
/*#
|
||||
Func: Len
|
||||
Proto: float:Vector v
|
||||
Desc: Return the length of this vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Len, 1, _T("x"))
|
||||
/*#
|
||||
Func: Len2
|
||||
Proto: float:Vector v
|
||||
Desc: Return the squared length of this vector.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Len2, 1, _T("x"))
|
||||
/*#
|
||||
Func: AngleWithVector
|
||||
Proto: float:Vector v
|
||||
Desc: Return the angle between two vectors.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, AngleWithVector, 2, _T("xx"))
|
||||
|
||||
/*#
|
||||
Func: Normalize
|
||||
Proto: Vector:float length = 1
|
||||
Desc: Return a normalized version of this vector scaled to a constant.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Normalize, -1, _T("xn"))
|
||||
/*#
|
||||
Func: Dist
|
||||
Proto: float:Vector v
|
||||
Desc: Return the distance between two vectors.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Dist, 2, _T("xx"))
|
||||
/*#
|
||||
Func: Dist2
|
||||
Proto: float:Vector v
|
||||
Desc: Return the squared distance between two vectors.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Dist2, 2, _T("xx"))
|
||||
/*#
|
||||
Func: Lerp
|
||||
Proto: float:Vector v,float t
|
||||
Desc: Return a linearly interpolated vector between two vectors.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Lerp, 3, _T("xnx"))
|
||||
/*#
|
||||
Func: Randomize
|
||||
Proto: Vector:Vector v,float min,float max
|
||||
Desc: Return a random vector in a given range.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Randomize, -2, _T(".nn"))
|
||||
|
||||
/*#
|
||||
Func: IsEqual
|
||||
Proto: bool:Vector v,float epsilon = 0.0001
|
||||
Desc: Test vectors for equality with a given espilon tolerance.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, IsEqual, -2, _T("xxn"))
|
||||
/*#
|
||||
Func: Print
|
||||
Proto: void:
|
||||
Desc: Dump this vector components to the engine log.
|
||||
#*/
|
||||
_MEMBER_FUNCTION(Vector, Print, -1, _T("x"))
|
||||
|
||||
_END_CLASS(Vector)
|
||||
|
||||
//-----------------------------------------------
|
||||
void UCBind_RegisterVector(HSQUIRRELVM vm)
|
||||
//-----------------------------------------------
|
||||
{
|
||||
_INIT_CLASS(vm, Vector);
|
||||
}
|
||||
142
include/modules/script_squirrel/engine_vm.cpp
Normal file
142
include/modules/script_squirrel/engine_vm.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "script_squirrel/engine_vm.h"
|
||||
#include "script_squirrel/cobject/cobject.h"
|
||||
#include "script_squirrel/cobject/cobject_decl.h"
|
||||
#include "script_squirrel/legacy/squirrel_binding.h"
|
||||
#include "script/scripted_object.h"
|
||||
#include "script/script_variant.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool EngineVM::Open()
|
||||
{
|
||||
if (!SquirrelVM::Open())
|
||||
return false;
|
||||
|
||||
#define __SQ_REGISTERINT(__NAME__, __V__) sq_pushstring(vm, __NAME__, -1); sq_pushinteger(vm, __V__); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushroottable(vm);
|
||||
|
||||
__SQ_REGISTERINT("objectTypeUndefined", typetag_Undefined)
|
||||
__SQ_REGISTERINT("objectTypeDeleted", typetag_Deleted)
|
||||
|
||||
__SQ_REGISTERINT("objectTypeEngine", typetag_Engine)
|
||||
__SQ_REGISTERINT("objectTypeResourceCache", typetag_ResourceSet)
|
||||
__SQ_REGISTERINT("objectTypeProject", typetag_Project)
|
||||
__SQ_REGISTERINT("objectTypeRenderer", typetag_Renderer)
|
||||
__SQ_REGISTERINT("objectTypeRaytracer", typetag_Raytracer)
|
||||
__SQ_REGISTERINT("objectTypeMixer", typetag_Mixer)
|
||||
__SQ_REGISTERINT("objectTypeScene", typetag_Scene3d)
|
||||
__SQ_REGISTERINT("objectTypeClock", typetag_Clock)
|
||||
|
||||
__SQ_REGISTERINT("objectTypeFont", typetag_Font)
|
||||
__SQ_REGISTERINT("objectTypeRasterFont", typetag_RasterFont)
|
||||
__SQ_REGISTERINT("objectTypeUI", typetag_Scene2d)
|
||||
__SQ_REGISTERINT("objectTypeUICursor", typetag_UICursor)
|
||||
__SQ_REGISTERINT("objectTypeWindow", typetag_Window)
|
||||
__SQ_REGISTERINT("objectTypeWidget", typetag_Widget)
|
||||
__SQ_REGISTERINT("objectTypeSizerWidget", typetag_SizerWidget)
|
||||
__SQ_REGISTERINT("objectTypeContainerWidget", typetag_ContainerWidget)
|
||||
__SQ_REGISTERINT("objectTypeSpacerWidget", typetag_SpacerWidget)
|
||||
__SQ_REGISTERINT("objectTypeCanvasWidget", typetag_CanvasWidget)
|
||||
__SQ_REGISTERINT("objectTypeTextWidget", typetag_TextWidget)
|
||||
__SQ_REGISTERINT("objectTypeBitmapWidget", typetag_BitmapWidget)
|
||||
__SQ_REGISTERINT("objectTypeCheckWidget", typetag_CheckWidget)
|
||||
__SQ_REGISTERINT("objectTypePicture", typetag_Picture)
|
||||
|
||||
__SQ_REGISTERINT("objectTypeGroup", typetag_Group)
|
||||
__SQ_REGISTERINT("objectTypeItem", typetag_Item)
|
||||
__SQ_REGISTERINT("objectTypeCamera", typetag_Camera)
|
||||
__SQ_REGISTERINT("objectTypeObject", typetag_Object)
|
||||
__SQ_REGISTERINT("objectTypeLight", typetag_Light)
|
||||
__SQ_REGISTERINT("objectTypeInstance", typetag_Instance)
|
||||
__SQ_REGISTERINT("objectTypeMotion", typetag_Motion)
|
||||
__SQ_REGISTERINT("objectTypeTrigger", typetag_Trigger)
|
||||
__SQ_REGISTERINT("objectTypePath", typetag_Path)
|
||||
|
||||
__SQ_REGISTERINT("objectTypeSound", typetag_Sound)
|
||||
__SQ_REGISTERINT("objectTypeTexture", typetag_Texture)
|
||||
__SQ_REGISTERINT("objectTypeGeometry", typetag_Geometry)
|
||||
__SQ_REGISTERINT("objectTypeMaterial", typetag_Material)
|
||||
__SQ_REGISTERINT("objectTypeColShape", typetag_ColShape)
|
||||
__SQ_REGISTERINT("objectTypeConstraint", typetag_Constraint)
|
||||
|
||||
__SQ_REGISTERINT("objectTypeMetafile", typetag_Metafile)
|
||||
__SQ_REGISTERINT("objectTypeMetatag", typetag_Metatag)
|
||||
|
||||
__SQ_REGISTERINT("objectTypeHidDevice", typetag_InputDevice)
|
||||
|
||||
__SQ_REGISTERINT("objectTypeEditorPlugin", typetag_EditorPlugin)
|
||||
|
||||
__SQ_REGISTERINT("objectTypeProjectScene", typetag_ProjectScene)
|
||||
__SQ_REGISTERINT("objectTypeProjectLayer", typetag_ProjectLayer)
|
||||
|
||||
__SQ_REGISTERINT("objectTypeAnimationSource", typetag_AutomationSource)
|
||||
__SQ_REGISTERINT("objectTypeAnimationSourceGroup", typetag_AutomationSourceGroup)
|
||||
|
||||
sq_pop(vm, 1);
|
||||
|
||||
_INIT_CLASS(vm, CObject);
|
||||
|
||||
RegisterAllSquirrelBinding(vm);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool EngineVM::PushVariant(const Variant &v)
|
||||
{
|
||||
if (v.type == Variant::Type_UserObject)
|
||||
return CObject::Push(vm, v.ptr, (CObjectType)v.typetag);
|
||||
return SquirrelVM::PushVariant(v);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int EngineVM::InvalidateNativeReference(void *ptr)
|
||||
{
|
||||
uint invalidated_count = 0;
|
||||
ListForeachPtr(CObject *, o, cobjects)
|
||||
if (o->native == ptr)
|
||||
{
|
||||
cobjects.Remove(o);
|
||||
|
||||
o->list_item = NULL;
|
||||
o->type = typetag_Deleted;
|
||||
o->native = NULL;
|
||||
|
||||
++invalidated_count;
|
||||
}
|
||||
|
||||
// __LOG_E__ << "Invalidate native object " << nString::Format("0x%x", ptr) << " - reference found: " << count << ", CObject left: " << safe_ptr_list.GetCount() << ".\n";
|
||||
return invalidated_count;
|
||||
}
|
||||
void EngineVM::ReleaseAllNativeReferences()
|
||||
{
|
||||
ListForeachPtr(CObject *, o, cobjects)
|
||||
o->Release();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void EngineVM::Close()
|
||||
{
|
||||
/*
|
||||
[EJ] We have to drop all native object references now. If we don't,
|
||||
native objects holding a reference to a script object will crash the VM
|
||||
when they try to release it from their destructor (hence making a
|
||||
reentrant call into the VM).
|
||||
*/
|
||||
ReleaseAllNativeReferences();
|
||||
|
||||
SquirrelVM::Close();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
161
include/modules/script_squirrel/engine_vm_debugger.cpp
Normal file
161
include/modules/script_squirrel/engine_vm_debugger.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "script_squirrel/engine_vm_debugger.h"
|
||||
#include "script_squirrel/cobject/vector_decl.h"
|
||||
#include "script_squirrel/cobject/cobject.h"
|
||||
#include "script_squirrel/engine_vm.h"
|
||||
#include "core/sound.h"
|
||||
#include "motion/motion.h"
|
||||
#include "scene3d/group.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/mcamera.h"
|
||||
#include "scene3d/mtrigger.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "project/project.h"
|
||||
#include "script/script_profiler.h"
|
||||
#include "script/scripted_object.h"
|
||||
#include "raytracer/raytracer_core.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
String SquirrelDebugger::FormatUserObjectParameter(CObjectType type)
|
||||
{
|
||||
// Check for null safe ptr.
|
||||
void *test;
|
||||
CObject::Get(vm, -1, &test);
|
||||
if (!test)
|
||||
return "Null";
|
||||
|
||||
// Get type specific data.
|
||||
switch (type)
|
||||
{
|
||||
case typetag_Group:
|
||||
{
|
||||
S3D::Group *group;
|
||||
CObject::Get(vm, -1, (void **)&group, type);
|
||||
return String::Format("(id='%s', items=%d, ...)", group->name.c_str(), group->GetItemList().GetCount());
|
||||
}
|
||||
case typetag_Motion:
|
||||
{
|
||||
Core::Motion *motion;
|
||||
CObject::Get(vm, -1, (void **)&motion, type);
|
||||
return String::Format("(id='%s', channels=%d, length=%.2fs, ...)", motion->name.c_str(), motion->GetChannelList().GetCount(), motion->GetDuration().toSec());
|
||||
}
|
||||
case typetag_Geometry:
|
||||
{
|
||||
Render::Geometry *geometry;
|
||||
CObject::Get(vm, -1, (void **)&geometry, type);
|
||||
return String::Format("(id='%s', vertex=%d, material=%d, ...)", geometry->name.c_str(), geometry->material_table.GetCount());
|
||||
}
|
||||
case typetag_Picture:
|
||||
{
|
||||
Picture *picture;
|
||||
CObject::Get(vm, -1, (void **)&picture, type);
|
||||
return String::Format("(w=%dpx, h=%dpx, ...)", picture->GetWidth(), picture->GetHeight());
|
||||
}
|
||||
case typetag_Texture:
|
||||
{
|
||||
Render::Texture *texture;
|
||||
CObject::Get(vm, -1, (void **)&texture, type);
|
||||
return String::Format("(id='%s', w=%dpx, h=%dpx, ...)", texture->name.c_str(), texture->GetWidth(), texture->GetHeight());
|
||||
}
|
||||
case typetag_Sound:
|
||||
{
|
||||
Audio::Sound *sound;
|
||||
CObject::Get(vm, -1, (void **)&sound, type);
|
||||
return String::Format("(id='%s')", sound->name.c_str());
|
||||
}
|
||||
case typetag_Object:
|
||||
{
|
||||
S3D::MObject *object;
|
||||
CObject::Get(vm, -1, (void **)&object, type);
|
||||
return String::Format("(id='%s', uid=%d, geometry='%s', ...)", object->name.c_str(), object->GetUid(), object->geometry.IsEmpty() ? "None" : object->geometry.c_str());
|
||||
}
|
||||
case typetag_Light:
|
||||
{
|
||||
S3D::MLight *light;
|
||||
CObject::Get(vm, -1, (void **)&light, type);
|
||||
return String::Format("(id='%s', uid=%d, diffuse=%.2f, specular=%.2f, ...)", light->name.toUtf8(), light->GetUid(), light->diffuse_intensity, light->specular_intensity);
|
||||
}
|
||||
case typetag_Camera:
|
||||
{
|
||||
S3D::MCamera *camera;
|
||||
CObject::Get(vm, -1, (void **)&camera, type);
|
||||
return String::Format("(id='%s', uid=%d, fov=%.2f, ...)", camera->name.toUtf8(), camera->GetUid(), camera->GetFov());
|
||||
}
|
||||
case typetag_Trigger:
|
||||
{
|
||||
S3D::MTrigger *trigger;
|
||||
CObject::Get(vm, -1, (void **)&trigger, type);
|
||||
return String::Format("(id='%s', uid=%d, ...)", trigger->name.toUtf8(), trigger->GetUid());
|
||||
}
|
||||
case typetag_Scene3d:
|
||||
{
|
||||
S3D::Scene *scene;
|
||||
CObject::Get(vm, -1, (void **)&scene, type);
|
||||
return String::Format("(id='%s', items=%d, ...)", scene->name.toUtf8(), scene->GetItemList().GetCount());
|
||||
}
|
||||
case typetag_Item:
|
||||
{
|
||||
S3D::MItem *item;
|
||||
CObject::Get(vm, -1, (void **)&item, type);
|
||||
return String::Format("(id='%s', uid=%d, scripted=%s, ...)", item->name.toUtf8(), item->GetUid(), item->scripted_object.IsValid() && item->scripted_object->GetUnitList().GetCount() ? "True" : "False");
|
||||
}
|
||||
case typetag_Raytracer:
|
||||
{
|
||||
Raytrace::Raytracer *ray;
|
||||
CObject::Get(vm, -1, (void **)&ray, type);
|
||||
Raytrace::Configuration cfg = ray->GetConfiguration();
|
||||
return String::Format("(aa=%s, gi=%s, interlaced=%s, ...)", cfg.trace_aa ? "True" : "False", cfg.trace_gi ? "True" : "False", cfg.interlaced ? "True" : "False");
|
||||
}
|
||||
case typetag_Material:
|
||||
{
|
||||
Render::Material *material;
|
||||
CObject::Get(vm, -1, (void **)&material, type);
|
||||
return String::Format("(id='%s', ...)", material->name.toUtf8());
|
||||
}
|
||||
case typetag_Metafile:
|
||||
{
|
||||
NML::File *metafile;
|
||||
CObject::Get(vm, -1, (void **)&metafile, type);
|
||||
return String::Format("(path='%s', ...)", metafile->name.toUtf8());
|
||||
}
|
||||
case typetag_Metatag:
|
||||
{
|
||||
NML::Tag *metatag;
|
||||
CObject::Get(vm, -1, (void **)&metatag, type);
|
||||
return String::Format("(id='%s', ...)", metatag->name.toUtf8());
|
||||
}
|
||||
case typetag_ColShape:
|
||||
{
|
||||
S3D::PhysicShape *shape;
|
||||
CObject::Get(vm, -1, (void **)&shape, type);
|
||||
|
||||
String _type = "...";
|
||||
switch (shape->GetType())
|
||||
{
|
||||
case S3D::PhysicShape::TypeBox: _type = "Box"; break;
|
||||
case S3D::PhysicShape::TypeCone: _type = "Cone"; break;
|
||||
case S3D::PhysicShape::TypeSphere: _type = "Sphere"; break;
|
||||
case S3D::PhysicShape::TypeConvex: _type = "Convex"; break;
|
||||
case S3D::PhysicShape::TypeMesh: _type = "Mesh"; break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
return String::Format("(type=%s, mass=%.2f, ...)", _type.toUtf8(), shape->mass);
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
return String("...");
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
EngineDebugger::EngineDebugger(EngineVM &vm) : SquirrelDebugger(vm) {}
|
||||
9
include/modules/script_squirrel/engine_vm_profiler.cpp
Normal file
9
include/modules/script_squirrel/engine_vm_profiler.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "script_squirrel/engine_vm_profiler.h"
|
||||
|
||||
using namespace GS::Script;
|
||||
23
include/modules/script_squirrel/legacy/ai_binding.cpp
Normal file
23
include/modules/script_squirrel/legacy/ai_binding.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
|
||||
|
||||
//-------------------------------------------
|
||||
void RegisterAIBinding(HSQUIRRELVM vm)
|
||||
//-------------------------------------------
|
||||
{
|
||||
/*#
|
||||
Topic: AI
|
||||
Type: Path
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: AIPath
|
||||
Desc: AI Path functions
|
||||
#*/
|
||||
}
|
||||
419
include/modules/script_squirrel/legacy/animation_binding.cpp
Normal file
419
include/modules/script_squirrel/legacy/animation_binding.cpp
Normal file
@ -0,0 +1,419 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "squirrel_binding.h"
|
||||
#include "binding_helpers.h"
|
||||
#include "motion/motion.h"
|
||||
#include "automation/automation_source_group.h"
|
||||
#include "automation/automation_player.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
using namespace GS::Automation;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger AnimationSourceSetLoopMode(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(source, Source, typetag_AutomationSource)
|
||||
__SQ_GETINT(loop_mode)
|
||||
__SQ_GETEND
|
||||
source->SetLoopMode((Curve::LoopMode)loop_mode);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger AnimationSourceSetLoop(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(source, Source, typetag_AutomationSource)
|
||||
__SQ_GETFLOAT(loop_start)
|
||||
__SQ_GETFLOAT(loop_end)
|
||||
__SQ_GETEND
|
||||
source->SetLoop(Time::fromSec(loop_start), Time::fromSec(loop_end));
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger AnimationSourceGetClock(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(source, Source, typetag_AutomationSource)
|
||||
__SQ_RETURNFLOAT(source->time.toSec())
|
||||
}
|
||||
SQInteger AnimationSourceSetClock(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(source, Source, typetag_AutomationSource)
|
||||
__SQ_GETFLOAT(time)
|
||||
__SQ_GETEND
|
||||
source->time = Time::fromSec(time);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger AnimationSourceGetClockScale(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(source, Source, typetag_AutomationSource)
|
||||
__SQ_RETURNFLOAT(source->time_scale)
|
||||
}
|
||||
SQInteger AnimationSourceSetClockScale(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(source, Source, typetag_AutomationSource)
|
||||
__SQ_GETFLOAT(scale)
|
||||
__SQ_GETEND
|
||||
source->time_scale = scale;
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger AnimationSourceIsRelative(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(source, Source, typetag_AutomationSource)
|
||||
__SQ_RETURNBOOL(source->relative);
|
||||
}
|
||||
SQInteger AnimationSourceSetRelative(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(source, Source, typetag_AutomationSource)
|
||||
__SQ_GETBOOL(relative)
|
||||
__SQ_GETEND
|
||||
source->relative = asbool(relative);
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger AnimationSourceSetWeight(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(source, Source, typetag_AutomationSource)
|
||||
__SQ_GETFLOAT(weight)
|
||||
__SQ_GETFLOAT(blend)
|
||||
__SQ_GETEND
|
||||
source->SetWeight(weight, blend);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger AnimationSourceStop(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(source, Source, typetag_AutomationSource)
|
||||
__SQ_GETFLOAT(blend)
|
||||
__SQ_GETEND
|
||||
source->Dispose(blend);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger AnimationSourceIsDone(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(source, Source, typetag_AutomationSource)
|
||||
__SQ_RETURNBOOL(source->IsDone());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Group
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger AnimationSourceGroupGetSourceCount(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(group, SourceGroup, typetag_AutomationSourceGroup)
|
||||
__SQ_RETURNINT(group->source_list.GetCount())
|
||||
}
|
||||
SQInteger AnimationSourceGroupGetSource(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, SourceGroup, typetag_AutomationSourceGroup)
|
||||
__SQ_GETINT(index)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(group->source_list[index], typetag_AutomationSource)
|
||||
}
|
||||
SQInteger AnimationSourceGroupAddSource(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, SourceGroup, typetag_AutomationSourceGroup)
|
||||
__SQ_GETSAFEPTR(source, Source, typetag_AutomationSource)
|
||||
__SQ_GETEND
|
||||
group->source_list.Add(source);
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger AnimationSourceGroupSetLoopMode(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, SourceGroup, typetag_AutomationSourceGroup)
|
||||
__SQ_GETINT(loop_mode)
|
||||
__SQ_GETEND
|
||||
group->SetLoopMode((Curve::LoopMode)loop_mode);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger AnimationSourceGroupSetLoop(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(group, SourceGroup, typetag_AutomationSourceGroup)
|
||||
__SQ_GETFLOAT(loop_start)
|
||||
__SQ_GETFLOAT(loop_end)
|
||||
__SQ_GETEND
|
||||
group->SetLoop(Time::fromSec(loop_start), Time::fromSec(loop_end));
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger AnimationSourceGroupGetClock(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(group, SourceGroup, typetag_AutomationSourceGroup)
|
||||
if (group->source_list.GetCount() == 0)
|
||||
return sq_throwerror(vm, "No animation source in group");
|
||||
__SQ_RETURNFLOAT(group->source_list[0]->time.toSec())
|
||||
}
|
||||
SQInteger AnimationSourceGroupSetClock(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, SourceGroup, typetag_AutomationSourceGroup)
|
||||
__SQ_GETFLOAT(time)
|
||||
__SQ_GETEND
|
||||
group->SetTime(Time::fromSec(time));
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger AnimationSourceGroupGetClockScale(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(group, SourceGroup, typetag_AutomationSourceGroup)
|
||||
if (group->source_list.GetCount() == 0)
|
||||
return sq_throwerror(vm, "No animation source in group");
|
||||
__SQ_RETURNFLOAT(group->source_list[0]->time_scale)
|
||||
}
|
||||
SQInteger AnimationSourceGroupSetClockScale(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, SourceGroup, typetag_AutomationSourceGroup)
|
||||
__SQ_GETFLOAT(scale)
|
||||
__SQ_GETEND
|
||||
group->SetTimeScale(scale);
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger AnimationSourceGroupSetRelative(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, SourceGroup, typetag_AutomationSourceGroup)
|
||||
__SQ_GETBOOL(relative)
|
||||
__SQ_GETEND
|
||||
group->SetRelative(asbool(relative));
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger AnimationSourceGroupSetWeight(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(group, SourceGroup, typetag_AutomationSourceGroup)
|
||||
__SQ_GETFLOAT(weight)
|
||||
__SQ_GETFLOAT(blend)
|
||||
__SQ_GETEND
|
||||
group->SetWeight(weight, blend);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger AnimationSourceGroupStop(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, SourceGroup, typetag_AutomationSourceGroup)
|
||||
__SQ_GETFLOAT(blend)
|
||||
__SQ_GETEND
|
||||
group->Dispose(blend);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger AnimationSourceGroupIsDone(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(group, SourceGroup, typetag_AutomationSourceGroup)
|
||||
__SQ_RETURNBOOL(group->IsDone());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------
|
||||
void RegisterAnimationBinding(HSQUIRRELVM vm)
|
||||
//--------------------------------------------------
|
||||
{
|
||||
/*#
|
||||
Topic: Animation
|
||||
Type: AnimationSourceGroup
|
||||
Type: AnimationSource
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: Animation Source
|
||||
Desc: Provides control over an animation source.
|
||||
#*/
|
||||
/*#
|
||||
Func: AnimationSourceSetLoopMode
|
||||
Proto: void:AnimationSource, AnimationLoopMode mode
|
||||
Desc: Set animation source loop mode.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceSetLoopMode, "AnimationSourceSetLoopMode", _SC(".xi"));
|
||||
/*#
|
||||
Func: AnimationSourceSetLoop
|
||||
Proto: void:AnimationSource, float loop_start, float loop_end
|
||||
Desc: Set animation source loop point.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceSetLoop, "AnimationSourceSetLoop", _SC(".xnn"));
|
||||
/*#
|
||||
Func: AnimationSourceGetClock
|
||||
Proto: float:AnimationSource
|
||||
Desc: Get animation source clock.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGetClock, "AnimationSourceGetClock", _SC(".x"));
|
||||
/*#
|
||||
Func: AnimationSourceSetClock
|
||||
Proto: void:AnimationSource, float clock
|
||||
Desc: Set animation source clock.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceSetClock, "AnimationSourceSetClock", _SC(".xn"));
|
||||
/*#
|
||||
Func: AnimationSourceGetClockScale
|
||||
Proto: float:AnimationSource
|
||||
Desc: Get animation source clock scale.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGetClockScale, "AnimationSourceGetClockScale", _SC(".x"));
|
||||
/*#
|
||||
Func: AnimationSourceSetClockScale
|
||||
Proto: void:AnimationSource, float clock_scale
|
||||
Desc: Set animation source clock scale.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceSetClockScale, "AnimationSourceSetClockScale", _SC(".xn"));
|
||||
/*#
|
||||
Func: AnimationSourceSetWeight
|
||||
Proto: void:AnimationSource, float weight, float blend
|
||||
Desc: Set animation source weight and weight blend duration.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceSetWeight, "AnimationSourceSetWeight", _SC(".xnn"));
|
||||
/*#
|
||||
Func: AnimationSourceIsRelative
|
||||
Proto: bool:AnimationSource
|
||||
Desc: Return the animation source evaluation mode..
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceIsRelative, "AnimationSourceIsRelative", _SC(".x"));
|
||||
/*#
|
||||
Func: AnimationSourceSetRelative
|
||||
Proto: void:AnimationSource, bool relative
|
||||
Desc: Set animation source evaluation mode to relative instead of absolute.<br>Relative source offsets the value they modify instead of replacing it.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceSetRelative, "AnimationSourceSetRelative", _SC(".xb"));
|
||||
/*#
|
||||
Func: AnimationSourceStop
|
||||
Proto: void:AnimationSource, float blend
|
||||
Desc: Stop an animation source. The motion weight can be brought down to 0 over a given blend duration before the source is stopped.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceStop, "AnimationSourceStop", _SC(".xn"));
|
||||
/*#
|
||||
Func: AnimationSourceIsDone
|
||||
Proto: bool:AnimationSource
|
||||
Desc: Returns true if this animation source is done playing.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceIsDone, "AnimationSourceIsDone", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: Animation Source Group
|
||||
Desc: Provides control over a group of animation sources.
|
||||
#*/
|
||||
/*#
|
||||
Func: AnimationSourceGroupGetSourceCount
|
||||
Proto: int:AnimationSourceGroup
|
||||
Desc: Return the number of animation sources in this group.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGroupGetSourceCount, "AnimationSourceGroupGetSourceCount", _SC(".x"));
|
||||
/*#
|
||||
Func: AnimationSourceGroupGetSource
|
||||
Proto: AnimationSource:AnimationSourceGroup, int index
|
||||
Desc: Return an animation source from the group.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGroupGetSource, "AnimationSourceGroupGetSource", _SC(".xi"));
|
||||
/*#
|
||||
Func: AnimationSourceGroupAddSource
|
||||
Proto: void:AnimationSourceGroup, AnimationSource
|
||||
Desc: Add an animation source to the group.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGroupAddSource, "AnimationSourceGroupAddSource", _SC(".xx"));
|
||||
/*#
|
||||
Func: AnimationSourceGroupSetLoopMode
|
||||
Proto: void:AnimationSourceGroup, AnimationLoopMode mode
|
||||
Desc: Set animation source group loop mode.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGroupSetLoopMode, "AnimationSourceGroupSetLoopMode", _SC(".xi"));
|
||||
/*#
|
||||
Func: AnimationSourceGroupSetLoop
|
||||
Proto: void:AnimationSourceGroup, float loop_start, float loop_end
|
||||
Desc: Set animation source group loop point.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGroupSetLoop, "AnimationSourceGroupSetLoop", _SC(".xnn"));
|
||||
|
||||
/*#
|
||||
Func: AnimationSourceGroupGetClock
|
||||
Proto: float:AnimationSourceGroup
|
||||
Desc: Get animation source group clock.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGroupGetClock, "AnimationSourceGroupGetClock", _SC(".x"));
|
||||
/*#
|
||||
Func: AnimationSourceGroupSetClock
|
||||
Proto: void:AnimationSourceGroup, float clock
|
||||
Desc: Set animation source group clock.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGroupSetClock, "AnimationSourceGroupSetClock", _SC(".xn"));
|
||||
|
||||
/*#
|
||||
Func: AnimationSourceGroupGetClockScale
|
||||
Proto: float:AnimationSourceGroup
|
||||
Desc: Get animation source group clock scale.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGroupGetClockScale, "AnimationSourceGroupGetClockScale", _SC(".x"));
|
||||
/*#
|
||||
Func: AnimationSourceGroupSetClockScale
|
||||
Proto: void:AnimationSourceGroup, float clock_scale
|
||||
Desc: Set animation source group clock scale.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGroupSetClockScale, "AnimationSourceGroupSetClockScale", _SC(".xn"));
|
||||
|
||||
/*#
|
||||
Func: AnimationSourceGroupSetWeight
|
||||
Proto: void:AnimationSourceGroup, float weight, float blend
|
||||
Desc: Set animation source group weight and weight blend duration.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGroupSetWeight, "AnimationSourceGroupSetWeight", _SC(".xnn"));
|
||||
/*#
|
||||
Func: AnimationSourceGroupSetRelative
|
||||
Proto: void:AnimationSourceGroup, bool relative
|
||||
Desc: Set animation source evaluation mode to relative instead of absolute.<br>Relative source offsets the value they modify instead of replacing it.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGroupSetRelative, "AnimationSourceGroupSetRelative", _SC(".xb"));
|
||||
/*#
|
||||
Func: AnimationSourceGroupStop
|
||||
Proto: void:AnimationSourceGroup, float blend
|
||||
Desc: Stop an animation source group. The motion weight can be brought down to 0 over a given blend duration before the source group is stopped.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGroupStop, "AnimationSourceGroupStop", _SC(".xn"));
|
||||
/*#
|
||||
Func: AnimationSourceGroupIsDone
|
||||
Proto: bool:AnimationSourceGroup
|
||||
Desc: Returns true if this animation source group is done playing.
|
||||
#*/
|
||||
sq_register(vm, AnimationSourceGroupIsDone, "AnimationSourceGroupIsDone", _SC(".x"));
|
||||
|
||||
// Push defines.
|
||||
sq_pushroottable(vm);
|
||||
|
||||
/*#
|
||||
Enum: AnimationLoopMode
|
||||
Values: AnimationConstant,AnimationRepeat,AnimationReset,AnimationOffsetRepeat,AnimationOscillate
|
||||
#*/
|
||||
sq_pushstring(vm, "AnimationConstant", -1); sq_pushinteger(vm, Curve::Constant); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "AnimationRepeat", -1); sq_pushinteger(vm, Curve::Repeat); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "AnimationReset", -1); sq_pushinteger(vm, Curve::Reset); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "AnimationOffsetRepeat", -1); sq_pushinteger(vm, Curve::OffsetAndRepeat); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "AnimationOscillate", -1); sq_pushinteger(vm, Curve::Oscillate); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
421
include/modules/script_squirrel/legacy/camera_binding.cpp
Normal file
421
include/modules/script_squirrel/legacy/camera_binding.cpp
Normal file
@ -0,0 +1,421 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/mcamera.h"
|
||||
#include "script_squirrel/cobject/matrix_decl.h"
|
||||
#include "core/renderer.h"
|
||||
#include "math/vector.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
static CObjectType camera_derived_types[] = { typetag_Item, typetag_Camera, typetag_Undefined };
|
||||
static CObjectType object_derived_types[] = { typetag_Item, typetag_Object, typetag_Undefined };
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger CameraGetItem(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(cam, MCamera, typetag_Camera)
|
||||
__SQ_RETURNSAFEPTR((MItem *)cam, typetag_Item)
|
||||
}
|
||||
SQInteger CameraGetFov(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types))
|
||||
__SQ_RETURNFLOAT(c->GetFov())
|
||||
}
|
||||
SQInteger CameraSetFov(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETFLOAT(f)
|
||||
__SQ_GETEND
|
||||
c->SetFov(f);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger CameraGetZoomFactor(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types))
|
||||
__SQ_RETURNFLOAT(c->zoom_factor)
|
||||
}
|
||||
SQInteger CameraSetZoomFactor(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETFLOAT(z)
|
||||
__SQ_GETEND
|
||||
c->SetZoomFactor(z);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger CameraSetFStop(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETFLOAT(f)
|
||||
__SQ_GETEND
|
||||
c->registry.CreateKey("PostProcess:Dof:FStop", f);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger CameraSetFocalDistance(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETFLOAT(f)
|
||||
__SQ_GETEND
|
||||
c->registry.CreateKey("PostProcess:Dof:FDist", f);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger CameraGetVisibleItems(HSQUIRRELVM vm) {
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETSAFEPTR(scene, Scene, typetag_Scene3d)
|
||||
__SQ_GETEND
|
||||
|
||||
sq_newarray(vm, 0);
|
||||
Vector4 cameraPos = c->GetMatrix().GetRow(3);
|
||||
Vector4 cameraForward = c->GetMatrix().GetRow(2); // Camera's forward vector
|
||||
|
||||
ListForeachPtr(MItem *, item, scene->GetItemList()) {
|
||||
if (item->GetItemType() == Type_Object) {
|
||||
if (MObject *o = (MObject *)item) {
|
||||
if (o->render_data.IsValid() && o->render_data->geometry.IsValid()) {
|
||||
Vector4 objectPos = o->GetMatrix().GetRow(3);
|
||||
Vector4 toObject = objectPos - cameraPos;
|
||||
|
||||
// Skip this object if it's too far
|
||||
float distance = toObject.Len();
|
||||
if (distance > 500) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if object is in front of the camera
|
||||
float dot = toObject.x * cameraForward.x + toObject.y * cameraForward.y + toObject.z * cameraForward.z;
|
||||
if (dot > 0) {
|
||||
// Perform frustum culling
|
||||
Frustum::Visibility vis = c->frustum.ClassifyMinMax(o->render_data->geometry->minmax, &o->GetMatrix());
|
||||
if (vis != Frustum::Outside) {
|
||||
CObject::Push(vm, (void *)item, typetag_Item);
|
||||
sq_arrayappend(vm, -2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
SQInteger CameraComputeProjectionMatrix(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETFRECT(viewport)
|
||||
__SQ_GETEND
|
||||
Matrix4 projection_matrix;
|
||||
c->ComputeProjectionMatrix(viewport, projection_matrix);
|
||||
__SQ_RETURNMATRIX4(projection_matrix)
|
||||
}
|
||||
*/
|
||||
SQInteger CameraSetAspectRatio(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETFLOAT(v)
|
||||
__SQ_GETEND
|
||||
c->aspect_ratio = v;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger CameraGetAspectRatio(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types))
|
||||
__SQ_RETURNFLOAT(c->aspect_ratio)
|
||||
}
|
||||
SQInteger CameraSetAspectRatioRefAxis(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETBOOL(v)
|
||||
__SQ_GETEND
|
||||
c->aspect_ratio_ref_yaxis = asbool(v);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger CameraSetClipping(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETFLOAT(n)
|
||||
__SQ_GETFLOAT(f)
|
||||
__SQ_GETEND
|
||||
c->z_near = n;
|
||||
c->z_far = f;
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
SQInteger CameraGetZNear(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNFLOAT(c->z_near)
|
||||
}
|
||||
|
||||
SQInteger CameraGetZFar(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNFLOAT(c->z_far)
|
||||
}
|
||||
|
||||
|
||||
SQInteger CameraCullObject(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETCOBJECTBASE(o, MObject, object_derived_types)
|
||||
__SQ_GETEND
|
||||
|
||||
Frustum::Visibility vis = Frustum::Outside;
|
||||
if (o->render_data.IsValid() && o->render_data->geometry.IsValid())
|
||||
vis = c->frustum.ClassifyMinMax(o->render_data->geometry->minmax, &o->GetMatrix());
|
||||
|
||||
__SQ_RETURNINT(int(vis))
|
||||
}
|
||||
SQInteger CameraCullPosition(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETVECTOR(p)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNINT(int(c->frustum.ClassifySet(1, &p)))
|
||||
}
|
||||
|
||||
SQInteger CameraGetFrustumVertices(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETEND
|
||||
|
||||
const Vector4* vtx = c->frustum.GetVertices();
|
||||
|
||||
sq_newarray(vm, 0);
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
PushVector(vm, vtx[i], false);
|
||||
sq_arrayappend(vm, -2);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger CameraWorldToScreen(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETSAFEPTR(renderer, Renderer, typetag_Renderer)
|
||||
__SQ_GETVECTOR(world)
|
||||
__SQ_GETEND
|
||||
Vector4 screen;
|
||||
if (!c->WorldToScreen(renderer->GetViewport(), world, screen))
|
||||
screen.Set(-1, -1, -1, -1);
|
||||
__SQ_RETURNVECTOR(screen)
|
||||
}
|
||||
SQInteger CameraScreenToWorld(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(4)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETSAFEPTR(renderer, Renderer, typetag_Renderer)
|
||||
__SQ_GETFLOAT(x)
|
||||
__SQ_GETFLOAT(y)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNVECTOR(c->ScreenToWorld(renderer->GetViewport(), x, y))
|
||||
}
|
||||
SQInteger CameraScreenToWorldPlane(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(5)
|
||||
__SQ_GETCOBJECTBASE(c, MCamera, camera_derived_types)
|
||||
__SQ_GETSAFEPTR(renderer, Renderer, typetag_Renderer)
|
||||
__SQ_GETFLOAT(x)
|
||||
__SQ_GETFLOAT(y)
|
||||
__SQ_GETFLOAT(z)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNVECTOR(c->ScreenToWorld(renderer->GetViewport(), x, y, z))
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------
|
||||
void RegisterCameraBinding(HSQUIRRELVM vm)
|
||||
//-------------------------------------------------------
|
||||
{
|
||||
/*#
|
||||
Topic: Camera
|
||||
Type: Camera
|
||||
Related: Item
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: CameraGeneric
|
||||
Desc: Generic functions
|
||||
#*/
|
||||
/*#
|
||||
Func: CameraGetItem
|
||||
Proto: Item:Camera
|
||||
Example: local camera_item = CameraGetItem(camera)
|
||||
Desc: Return camera item.
|
||||
#*/
|
||||
sq_register(vm, CameraGetItem, "CameraGetItem", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: CameraAR
|
||||
Desc: Aspect ratio functions.
|
||||
#*/
|
||||
/*#
|
||||
Func: CameraSetAspectRatio
|
||||
Proto: void:Camera,float aspect_ratio
|
||||
Desc: Set camera aspect ratio.
|
||||
#*/
|
||||
sq_register(vm, CameraSetAspectRatio, "CameraSetAspectRatio", _SC(".xn"));
|
||||
/*#
|
||||
Func: CameraGetAspectRatio
|
||||
Proto: float:Camera
|
||||
Desc: Get camera aspect ratio.
|
||||
#*/
|
||||
sq_register(vm, CameraGetAspectRatio, "CameraGetAspectRatio", _SC(".x"));
|
||||
/*#
|
||||
Func: CameraSetAspectRatioRefAxis
|
||||
Proto: void:Camera,bool use_Y_axis
|
||||
Desc: Set camera aspect ratio correction to be done on the vertical screen axis (Y) instead of the horizontal axis (X).
|
||||
#*/
|
||||
sq_register(vm, CameraSetAspectRatioRefAxis, "CameraSetAspectRatioRefAxis", _SC(".xb"));
|
||||
|
||||
/*#
|
||||
Section: CameraViewport
|
||||
Desc: Viewport functions
|
||||
#*/
|
||||
/*#
|
||||
Func: CameraCullObject
|
||||
Proto: VisibilityFlags:Camera camera_to_cull_against,Object object_to_cull
|
||||
Desc: Cull an object against the camera frustum. Returns a visibility flag mask.
|
||||
#*/
|
||||
sq_register(vm, CameraCullObject, "CameraCullObject", _SC(".xx"));
|
||||
/*#
|
||||
Func: CameraCullPosition
|
||||
Proto: VisibilityFlags:Camera camera_to_cull_against,Vector world_position
|
||||
Desc: Cull a position in world space against the camera frustum. Returns a visibility flag mask.
|
||||
#*/
|
||||
sq_register(vm, CameraCullPosition, "CameraCullPosition", _SC(".xx"));
|
||||
|
||||
sq_register(vm, CameraGetFrustumVertices, "CameraGetFrustumVertices", _SC(".x"));
|
||||
sq_register(vm, CameraGetZNear, "CameraGetZNear", _SC(".x"));
|
||||
sq_register(vm, CameraGetZFar, "CameraGetZFar", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Func: CameraGetFov
|
||||
Proto: float:Camera
|
||||
Desc: Get camera fov in radian.
|
||||
#*/
|
||||
sq_register(vm, CameraGetFov, "CameraGetFov", _SC(".x"));
|
||||
/*#
|
||||
Func: CameraSetFov
|
||||
Proto: void:Camera,float fov_in_radian
|
||||
Example: CameraSetFov(camera, Deg(60))
|
||||
Desc: Get camera fov in radian.
|
||||
#*/
|
||||
sq_register(vm, CameraSetFov, "CameraSetFov", _SC(".xn"));
|
||||
|
||||
/*#
|
||||
Func: CameraGetZoomFactor
|
||||
Proto: float:Camera
|
||||
Desc: Get camera zoom.
|
||||
#*/
|
||||
sq_register(vm, CameraGetZoomFactor, "CameraGetZoomFactor", _SC(".x"));
|
||||
/*#
|
||||
Func: CameraSetZoomFactor
|
||||
Proto: void:Camera,float zoom_factor
|
||||
Example: CameraSetZoomFactor(camera, 3.2)
|
||||
Desc: Set camera zoom.
|
||||
#*/
|
||||
sq_register(vm, CameraSetZoomFactor, "CameraSetZoomFactor", _SC(".xn"));
|
||||
|
||||
|
||||
/*#
|
||||
Func: CameraSetFocalDistance
|
||||
Proto: void:Camera,float distance_in_meters
|
||||
Example:
|
||||
// Set focus 10 meters from camera. Objects closer or father than 10 meters will appear out of focus.
|
||||
CameraSetFocalDistance(camera, Mtr(10))
|
||||
Desc: Set camera focal distance, set to 0 or less to disable depth of field on the camera.
|
||||
#*/
|
||||
sq_register(vm, CameraSetFocalDistance, "CameraSetFocalDistance", _SC(".xn"));
|
||||
/*#
|
||||
Func: CameraSetFStop
|
||||
Proto: void:Camera,float fstop_in_meters
|
||||
Example: CameraSetFStop(camera, Mtr(4))
|
||||
Desc: Set camera f-stop, set to 0 or less to disable depth of field on the camera.
|
||||
#*/
|
||||
sq_register(vm, CameraSetFStop, "CameraSetFStop", _SC(".xn"));
|
||||
/*#
|
||||
Func: CameraSetClipping
|
||||
Proto: void:camera,float near, float far
|
||||
Example: CameraSetClipping(camera, Cm(1), Mtr(100))
|
||||
Desc: Set camera near and far clipping planes.
|
||||
#*/
|
||||
sq_register(vm, CameraSetClipping, "CameraSetClipping", _SC(".xnn"));
|
||||
/*#
|
||||
Func: CameraWorldToScreen
|
||||
Proto: vector:Camera,Renderer,Vector world_position
|
||||
Example:
|
||||
// Project world position {10,5,1} on the screen.
|
||||
local p2d = CameraWorldToScreen(camera, g_render, Vector(10, 5, 1))
|
||||
Desc: Transform a world space position to a normalized screen space position, in the range { [0;1], [0;1] }.
|
||||
#*/
|
||||
sq_register(vm, CameraWorldToScreen, "CameraWorldToScreen", _SC(".xxx"));
|
||||
/*#
|
||||
Func: CameraScreenToWorld
|
||||
Proto: vector:Camera,Renderer,float x,float y
|
||||
Example:
|
||||
// Transform the middle of the screen to a 3d world position 1 meter away from the camera.
|
||||
local wp = CameraScreenToWorld(camera, g_render, 0.5, 0.5)
|
||||
Desc: Transform a normalized screen space position to a world space position.<br>
|
||||
The screen space position is the result of a projection on the Z=1 imaginary plane, situated 1 meter in front of the camera.
|
||||
See: CameraScreenToWorldPlane
|
||||
#*/
|
||||
sq_register(vm, CameraScreenToWorld, "CameraScreenToWorld", _SC(".xxnn"));
|
||||
/*#
|
||||
Func: CameraScreenToWorldPlane
|
||||
Proto: vector:Camera,Renderer,float x,float y,float plane_distance_in_meters
|
||||
Desc: Transform a normalized screen space position to a world space position.<br>
|
||||
The screen space position is the result of a projection on an imaginary plane situated in front of the camera.
|
||||
#*/
|
||||
sq_register(vm, CameraScreenToWorldPlane, "CameraScreenToWorldPlane", _SC(".xxnnn"));
|
||||
|
||||
sq_pushroottable(vm);
|
||||
|
||||
/*#
|
||||
Enum: VisibilityFlags
|
||||
Desc: Reported by the visibility functions, visibility can be total, partial or null.
|
||||
Values: VisibilityOutside,VisibilityClipped,VisibilityInside
|
||||
#*/
|
||||
sq_pushstring(vm, "VisibilityOutside", -1); sq_pushinteger(vm, Frustum::Outside); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "VisibilityClipped", -1); sq_pushinteger(vm, Frustum::Clipped); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "VisibilityInside", -1); sq_pushinteger(vm, Frustum::Inside); sq_newslot(vm, -3, true);
|
||||
/*#
|
||||
Func: CameraGetVisibleItems
|
||||
Proto: array:Camera,Scene3d
|
||||
Desc: Get all visible items in the camera frustum.
|
||||
#*/
|
||||
sq_register(vm, CameraGetVisibleItems, "CameraGetVisibleItems", _SC(".xx"));
|
||||
|
||||
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
73
include/modules/script_squirrel/legacy/clock_binding.cpp
Normal file
73
include/modules/script_squirrel/legacy/clock_binding.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "script_squirrel/cobject/matrix_decl.h"
|
||||
#include "core/clock.h"
|
||||
#include <windows.h>
|
||||
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ClockReset(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(clock, GS::Core::Clock, typetag_Clock)
|
||||
clock->Reset();
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ClockGetCounter(HSQUIRRELVM vm)
|
||||
{
|
||||
// Get frequency
|
||||
LARGE_INTEGER frequency;
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
LARGE_INTEGER counter;
|
||||
QueryPerformanceCounter(&counter);
|
||||
__SQ_RETURNINT(counter.QuadPart)
|
||||
}
|
||||
SQInteger ClockGetFrequency(HSQUIRRELVM vm)
|
||||
{
|
||||
// Get frequency
|
||||
LARGE_INTEGER frequency;
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
__SQ_RETURNINT(frequency.QuadPart)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterClockBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Clock
|
||||
Type: Clock
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: ClockGeneral
|
||||
Desc: General functions
|
||||
#*/
|
||||
/*#
|
||||
Func: ClockReset
|
||||
Proto: void:Clock
|
||||
Desc: Reset a clock object.
|
||||
#*/
|
||||
sq_register(vm, ClockReset, "ClockReset", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Func: ClockGetCounter
|
||||
Proto: int:Clock
|
||||
Desc: Get the counter of a clock object.
|
||||
#*/
|
||||
sq_register(vm, ClockGetCounter, "ClockGetCounter", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Func: ClockGetFrequency
|
||||
Proto: int:Clock
|
||||
Desc: Get the frequency of a clock object.
|
||||
#*/
|
||||
sq_register(vm, ClockGetFrequency, "ClockGetFrequency", _SC(".x"));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
541
include/modules/script_squirrel/legacy/collision_binding.cpp
Normal file
541
include/modules/script_squirrel/legacy/collision_binding.cpp
Normal file
@ -0,0 +1,541 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "scene3d/mitem.h"
|
||||
#include "binding_helpers.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#define __SQ_TEST_ITEM_PHYSIC if (!item->physic_item) return sq_throwerror(vm, "No physic interface.");
|
||||
|
||||
SQInteger ItemSetSelfMask(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(item, MItem, typetag_Item)
|
||||
__SQ_GETINT(mask)
|
||||
__SQ_GETEND
|
||||
__SQ_TEST_ITEM_PHYSIC
|
||||
item->physic_item->SetSelfMask(mask);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ItemCollisionActivate(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(item, MItem, typetag_Item)
|
||||
__SQ_GETBOOL(active)
|
||||
__SQ_GETEND
|
||||
__SQ_TEST_ITEM_PHYSIC
|
||||
item->physic_item->SetActive(asbool(active));
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ItemSetCollisionMask(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(item, MItem, typetag_Item)
|
||||
__SQ_GETINT(mask)
|
||||
__SQ_GETEND
|
||||
__SQ_TEST_ITEM_PHYSIC
|
||||
item->physic_item->SetCollisionMask(mask);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ItemGetShapeFromIndex(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(item, MItem, typetag_Item)
|
||||
__SQ_GETINT(idx)
|
||||
__SQ_GETEND
|
||||
__SQ_TEST_ITEM_PHYSIC
|
||||
if (idx < (SQInteger)item->physic_item_desc.shape_list.GetCount())
|
||||
__SQ_RETURNSAFEPTR(item->physic_item_desc.shape_list[idx], typetag_ColShape)
|
||||
__SQ_RETURNNULL
|
||||
}
|
||||
SQInteger ItemAddCollisionShape(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(item, MItem, typetag_Item)
|
||||
__SQ_TEST_ITEM_PHYSIC
|
||||
PhysicShape *shape = new PhysicShape;
|
||||
if (!shape)
|
||||
return sq_throwerror(vm, "Failed to allocate collision shape.");
|
||||
item->physic_item_desc.shape_list.Add(shape);
|
||||
__SQ_RETURNSAFEPTR(shape, typetag_ColShape)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ShapeSetMesh(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_GETSTRING(path)
|
||||
bool r = path ? shape->Set(PhysicShape::TypeMesh, path) : false;
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(r)
|
||||
}
|
||||
SQInteger ShapeSetConvex(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_GETSTRING(path)
|
||||
bool r = path ? shape->Set(PhysicShape::TypeConvex, path) : false;
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(r)
|
||||
}
|
||||
SQInteger ShapeSetSphere(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_GETFLOAT(radius)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(shape->Set(PhysicShape::TypeSphere, Vector4(radius, 0, 0)))
|
||||
}
|
||||
SQInteger ShapeSetBox(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_GETVECTOR(scale)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(shape->Set(PhysicShape::TypeBox, scale))
|
||||
}
|
||||
SQInteger ShapeSetCapsule(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_GETFLOAT(radius)
|
||||
__SQ_GETFLOAT(length)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(shape->Set(PhysicShape::TypeCapsule, Vector4(radius, length, 0.0)))
|
||||
}
|
||||
SQInteger ShapeSetCylinder(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_GETFLOAT(radius)
|
||||
__SQ_GETFLOAT(length)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(shape->Set(PhysicShape::TypeCylinder, Vector4(radius, length, 0.0)))
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ShapeGetItem(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_RETURNSAFEPTR(NULL, typetag_Item);
|
||||
}
|
||||
SQInteger ShapeGetPosition(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_RETURNVECTOR(shape->position)
|
||||
}
|
||||
SQInteger ShapeSetPosition(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_GETVECTOR(p)
|
||||
__SQ_GETEND
|
||||
shape->position = p;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ShapeGetRotation(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_RETURNVECTOR(shape->rotation)
|
||||
}
|
||||
SQInteger ShapeSetRotation(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_GETVECTOR(e)
|
||||
__SQ_GETEND
|
||||
shape->rotation = e;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ShapeSetRestitution(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_GETFLOAT(r)
|
||||
__SQ_GETEND
|
||||
shape->restitution = r;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ShapeSetFriction(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_GETFLOAT(df)
|
||||
__SQ_GETFLOAT(sf)
|
||||
__SQ_GETEND
|
||||
shape->dynamic_friction = df;
|
||||
shape->static_friction = sf;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ShapeGetMass(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_RETURNFLOAT(shape->mass)
|
||||
}
|
||||
SQInteger ShapeSetMass(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(shape, PhysicShape, typetag_ColShape)
|
||||
__SQ_GETFLOAT(mass)
|
||||
__SQ_GETEND
|
||||
shape->mass = mass;
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// //poly poly intersection
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Gather up one-dimensional extents of the projection of the polygon
|
||||
// onto this axis.
|
||||
void gatherPolygonProjectionExtents(GS::Array<GS::Vector4> poly, GS::Vector4 v, float &outMin, float &outMax)
|
||||
{
|
||||
// Initialize extents to a single point, the first vertex
|
||||
outMin = outMax = v.Dot(poly[0]);
|
||||
|
||||
// Now scan all the rest, growing extents to include them
|
||||
for (uint i = 1; i < poly.GetCount(); ++i) {
|
||||
float d = v.Dot(poly[i]);
|
||||
if (d < outMin)
|
||||
outMin = d;
|
||||
else if (d > outMax)
|
||||
outMax = d;
|
||||
}
|
||||
}
|
||||
// Helper routine: test if two convex polygons overlap, using only the edges of
|
||||
// the first polygon (polygon "a") to build the list of candidate separating axes.
|
||||
bool findSeparatingAxis(GS::Array<Vector4> poly_a, GS::Array<Vector4> poly_b)
|
||||
{
|
||||
// Iterate over all the edges
|
||||
uint prev = poly_a.GetCount() - 1;
|
||||
for (uint cur = 0; cur < poly_a.GetCount(); ++cur)
|
||||
{
|
||||
// Get edge vector. (Assume operator- is overloaded)
|
||||
GS::Vector4 edge = poly_a[cur] - poly_a[prev];
|
||||
edge.y = 0;
|
||||
edge.Normalize();
|
||||
|
||||
// Rotate vector 90 degrees (doesn't matter which way) to get
|
||||
// candidate separating axis.
|
||||
GS::Vector4 v(edge.z, 0, -edge.x);
|
||||
|
||||
// Gather extents of both polygons projected onto this axis
|
||||
float result_poly_a_min, result_poly_a_max;
|
||||
gatherPolygonProjectionExtents(poly_a, v, result_poly_a_min, result_poly_a_max);
|
||||
float result_poly_b_min, result_poly_b_max;
|
||||
gatherPolygonProjectionExtents(poly_b, v, result_poly_b_min, result_poly_b_max);
|
||||
|
||||
// Is this a separating axis?
|
||||
if (result_poly_a_max < result_poly_b_min) return true;
|
||||
if (result_poly_b_max < result_poly_a_min) return true;
|
||||
|
||||
// Next edge, please
|
||||
prev = cur;
|
||||
}
|
||||
|
||||
// Failed to find a separating axis
|
||||
return false;
|
||||
}
|
||||
|
||||
// Here is our high level entry point. It tests whether two polygons intersect. The
|
||||
// polygons must be convex, and they must not be degenerate.
|
||||
bool convexPolygonOverlap(GS::Array<GS::Vector4> poly_a, GS::Array<Vector4> poly_b) //poly[a, b, c, d]
|
||||
{
|
||||
// First, use all of A's edges to get candidate separating axes
|
||||
if (findSeparatingAxis(poly_a, poly_b))
|
||||
return false;
|
||||
|
||||
// Now swap roles, and use B's edges
|
||||
if (findSeparatingAxis(poly_b, poly_a))
|
||||
return false;
|
||||
|
||||
// No separating axis found. They must overlap
|
||||
return true;
|
||||
}
|
||||
|
||||
SQInteger convexPolygonOverlapBind(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
|
||||
GS::Array<GS::Vector4> poly_a(4);
|
||||
sq_pushnull(vm);//null iterator
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
sq_next(vm, __SQ_STACKPOS - 1);
|
||||
GetVector(vm, -1, poly_a[i]);
|
||||
sq_pop(vm, 2);
|
||||
}
|
||||
sq_pop(vm, 1); //pops the null iterator
|
||||
|
||||
__SQ_GETUPDATESTACK
|
||||
GS::Array<GS::Vector4> poly_b(4);
|
||||
sq_pushnull(vm);//null iterator
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
sq_next(vm, __SQ_STACKPOS - 1);
|
||||
GetVector(vm, -1, poly_b[i]);
|
||||
sq_pop(vm, 2);
|
||||
}
|
||||
sq_pop(vm, 1); //pops the null iterator
|
||||
|
||||
__SQ_GETEND
|
||||
|
||||
__SQ_RETURNBOOL(convexPolygonOverlap(poly_a, poly_b));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
bool PointInPoly2D(GS::Vector4 point, GS::Array<GS::Vector4> poly) // poly = [Vector(), Vector(), Vector(), Vector()]
|
||||
//------------------------------------------------------------
|
||||
{
|
||||
bool oddNodes = false;
|
||||
float x2 = poly[3].x;
|
||||
float z2 = poly[3].z;
|
||||
float x1, z1;
|
||||
|
||||
// vertex a
|
||||
x1 = poly[0].x;
|
||||
z1 = poly[0].z;
|
||||
if (((z1 < point.z) && (z2 >= point.z)) || (z1 >= point.z) && (z2 < point.z)) {
|
||||
if ((point.z - z1) / (z2 - z1) * (x2 - x1) < (point.x - x1))
|
||||
oddNodes = !oddNodes;
|
||||
}
|
||||
|
||||
x2 = x1;
|
||||
z2 = z1;
|
||||
|
||||
// vertex b
|
||||
x1 = poly[1].x;
|
||||
z1 = poly[1].z;
|
||||
if (((z1 < point.z) && (z2 >= point.z)) || (z1 >= point.z) && (z2 < point.z)) {
|
||||
if ((point.z - z1) / (z2 - z1) * (x2 - x1) < (point.x - x1))
|
||||
oddNodes = !oddNodes;
|
||||
}
|
||||
|
||||
x2 = x1;
|
||||
z2 = z1;
|
||||
|
||||
// vertex c
|
||||
x1 = poly[2].x;
|
||||
z1 = poly[2].z;
|
||||
if (((z1 < point.z) && (z2 >= point.z)) || (z1 >= point.z) && (z2 < point.z)) {
|
||||
if ((point.z - z1) / (z2 - z1) * (x2 - x1) < (point.x - x1))
|
||||
oddNodes = !oddNodes;
|
||||
}
|
||||
|
||||
x2 = x1;
|
||||
z2 = z1;
|
||||
|
||||
// vertex d
|
||||
x1 = poly[3].x;
|
||||
z1 = poly[3].z;
|
||||
if (((z1 < point.z) && (z2 >= point.z)) || (z1 >= point.z) && (z2 < point.z)) {
|
||||
if ((point.z - z1) / (z2 - z1) * (x2 - x1) < (point.x - x1))
|
||||
oddNodes = !oddNodes;
|
||||
}
|
||||
|
||||
return oddNodes;
|
||||
}
|
||||
|
||||
SQInteger PointInPoly2DBind(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
|
||||
__SQ_GETVECTOR(p);
|
||||
|
||||
GS::Array<GS::Vector4> poly_a(4);
|
||||
sq_pushnull(vm);//null iterator
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
sq_next(vm, __SQ_STACKPOS - 1);
|
||||
GetVector(vm, -1, poly_a[i]);
|
||||
sq_pop(vm, 2);
|
||||
}
|
||||
sq_pop(vm, 1); //pops the null iterator
|
||||
|
||||
__SQ_GETUPDATESTACK
|
||||
__SQ_GETEND
|
||||
|
||||
__SQ_RETURNBOOL(PointInPoly2D(p, poly_a));
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
void RegisterCollisionBinding(HSQUIRRELVM vm)
|
||||
//----------------------------------------------------------
|
||||
{
|
||||
/*#
|
||||
Func: convexPolygonOverlapBind
|
||||
Proto: void:array polyA, array polyB
|
||||
Desc: return if the 2 poly overlap
|
||||
#*/
|
||||
sq_register(vm, convexPolygonOverlapBind, "convexPolygonOverlapBind", _SC(".aa"));
|
||||
/*#
|
||||
Func: convexPolygonOverlapBind
|
||||
Proto: void:Vector p, array polyA
|
||||
Desc: return if the 2 poly overlap
|
||||
#*/
|
||||
sq_register(vm, PointInPoly2DBind, "PointInPoly2DBind", _SC(".xa"));
|
||||
/*#
|
||||
Topic: Collision
|
||||
Type: ColShape
|
||||
#*/
|
||||
/*#
|
||||
Section: CollisionShapeType
|
||||
Desc: Collision Shape Type functions
|
||||
#*/
|
||||
/*#
|
||||
Func: ShapeSetMesh
|
||||
Proto: bool:ColShape shape,string path
|
||||
Desc: Set the shape as a collision mesh.
|
||||
#*/
|
||||
sq_register(vm, ShapeSetMesh, "ShapeSetMesh", _SC(".xs"));
|
||||
/*#
|
||||
Func: ShapeSetConvex
|
||||
Proto: bool:ColShape shape,string path
|
||||
Desc: Set the shape as a convex collision.
|
||||
#*/
|
||||
sq_register(vm, ShapeSetConvex, "ShapeSetConvex", _SC(".xs"));
|
||||
/*#
|
||||
Func: ShapeSetSphere
|
||||
Proto: bool:ColShape shape,float radius
|
||||
Desc: Set the shape as a sphere.
|
||||
#*/
|
||||
sq_register(vm, ShapeSetSphere, "ShapeSetSphere", _SC(".xn"));
|
||||
/*#
|
||||
Func: ShapeSetBox
|
||||
Proto: bool:ColShape shape,Vector dimensions
|
||||
Desc: Set the shape as a box collision shape.
|
||||
#*/
|
||||
sq_register(vm, ShapeSetBox, "ShapeSetBox", _SC(".xx"));
|
||||
/*#
|
||||
Func: ShapeSetCapsule
|
||||
Proto: bool:ColShape shape,float radius,float length
|
||||
Desc: Set the shape as a Z-oriented capsule collision shape.
|
||||
#*/
|
||||
sq_register(vm, ShapeSetCapsule, "ShapeSetCapsule", _SC(".xnn"));
|
||||
/*#
|
||||
Func: ShapeSetCylinder
|
||||
Proto: bool:ColShape shape,float radius,float length
|
||||
Desc: Set the shape as a Z-oriented cylinder collision shape.
|
||||
#*/
|
||||
sq_register(vm, ShapeSetCylinder, "ShapeSetCylinder", _SC(".xnn"));
|
||||
|
||||
/*#
|
||||
Section: CollisionShape
|
||||
Desc: Collision Shape functions
|
||||
#*/
|
||||
/*#
|
||||
Func: ShapeSetPosition
|
||||
Proto: void:ColShape shape,Vector position
|
||||
Desc: Set the collision shape position in item space.
|
||||
#*/
|
||||
sq_register(vm, ShapeSetPosition, "ShapeSetPosition", _SC(".xx"));
|
||||
/*#
|
||||
Func: ShapeGetPosition
|
||||
Proto: Vector:ColShape shape
|
||||
Desc: Get the collision shape position in item space.
|
||||
#*/
|
||||
sq_register(vm, ShapeGetPosition, "ShapeGetPosition", _SC(".x"));
|
||||
/*#
|
||||
Func: ShapeSetRotation
|
||||
Proto: void:ColShape shape,Vector position
|
||||
Desc: Set the collision shape position from a Euler triplet in item space.
|
||||
#*/
|
||||
sq_register(vm, ShapeSetRotation, "ShapeSetRotation", _SC(".xx"));
|
||||
/*#
|
||||
Func: ShapeGetRotation
|
||||
Proto: Vector:ColShape shape
|
||||
Desc: Get the collision shape rotation as an Euler triplet in item space.
|
||||
#*/
|
||||
sq_register(vm, ShapeGetRotation, "ShapeGetRotation", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Func: ShapeSetMass
|
||||
Proto: void:ColShape shape,float mass
|
||||
Desc: Set the collision shape mass. Do not forget to update the item collision setup to update changes.
|
||||
#*/
|
||||
sq_register(vm, ShapeSetMass, "ShapeSetMass", _SC(".xn"));
|
||||
/*#
|
||||
Func: ShapeGetMass
|
||||
Proto: float:ColShape shape
|
||||
Desc: Get the collision shape mass.
|
||||
#*/
|
||||
sq_register(vm, ShapeGetMass, "ShapeGetMass", _SC(".x"));
|
||||
/*#
|
||||
Func: ShapeSetFriction
|
||||
Proto: void:ColShape shape,float dynamic_friction,float static_friction
|
||||
Desc: Set collision shape dynamic and static friction.
|
||||
#*/
|
||||
sq_register(vm, ShapeSetFriction, "ShapeSetFriction", _SC(".xnn"));
|
||||
/*#
|
||||
Func: ShapeSetRestitution
|
||||
Proto: void:ColShape shape,float restitution
|
||||
Desc: Set collision shape restitution (1 for a perfect elastic collision).
|
||||
#*/
|
||||
sq_register(vm, ShapeSetRestitution, "ShapeSetRestitution", _SC(".xn"));
|
||||
/*#
|
||||
Func: ShapeGetItem
|
||||
Proto: Item:ColShape shape
|
||||
Desc: Get the item this collision shape belongs to.
|
||||
#*/
|
||||
sq_register(vm, ShapeGetItem, "ShapeGetItem", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: CollisionItem
|
||||
Desc: Item functions
|
||||
#*/
|
||||
/*#
|
||||
Func: ItemAddCollisionShape
|
||||
Proto: ColShape:Item
|
||||
Desc: Add a new collision shape to item.
|
||||
#*/
|
||||
sq_register(vm, ItemAddCollisionShape, "ItemAddCollisionShape", _SC(".x"));
|
||||
/*#
|
||||
Func: ItemCollisionActivate
|
||||
Proto: void:Item,bool active
|
||||
Desc: Activate or deactivate item collision.
|
||||
#*/
|
||||
sq_register(vm, ItemCollisionActivate, "ItemCollisionActivate", _SC(".xb"));
|
||||
/*#
|
||||
Func: ItemSetSelfMask
|
||||
Proto: void:Item,int self_mask
|
||||
Desc: Set item self mask, this mask is a bit field.
|
||||
#*/
|
||||
sq_register(vm, ItemSetSelfMask, "ItemSetSelfMask", _SC(".xi"));
|
||||
/*#
|
||||
Func: ItemSetCollisionMask
|
||||
Proto: void:Item,int collision_mask
|
||||
Desc: Set item collision mask, this mask is a bit field.
|
||||
#*/
|
||||
sq_register(vm, ItemSetCollisionMask, "ItemSetCollisionMask", _SC(".xi"));
|
||||
/*#
|
||||
Func: ItemGetShapeFromIndex
|
||||
Proto: ColShape:item,int index
|
||||
Desc: Get item collision shape from index.
|
||||
#*/
|
||||
sq_register(vm, ItemGetShapeFromIndex, "ItemGetShapeFromIndex", _SC(".xi"));
|
||||
|
||||
// Push defines.
|
||||
sq_pushroottable(vm);
|
||||
|
||||
/*#
|
||||
Enum: ShapeMask
|
||||
Desc: Shape mask to filter out certain type of shape from intersection tests.
|
||||
Values: CollisionTraceMesh,CollisionTraceSphere,CollisionTraceCuboid,CollisionTraceAll
|
||||
#*/
|
||||
sq_pushstring(vm, "CollisionTraceMesh", -1); sq_pushinteger(vm, -1); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "CollisionTraceSphere", -1); sq_pushinteger(vm, -1); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "CollisionTraceCuboid", -1); sq_pushinteger(vm, -1); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "CollisionTraceAll", -1); sq_pushinteger(vm, ~0); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
112
include/modules/script_squirrel/legacy/emitter_binding.cpp
Normal file
112
include/modules/script_squirrel/legacy/emitter_binding.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/memitter.h"
|
||||
#include "core/engine.h"
|
||||
#include "core/graphic_resource_factory.h"
|
||||
|
||||
using namespace GS::Core;
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
SQInteger EmitterSetParticleModel(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(e, MEmitter, typetag_Emitter)
|
||||
__SQ_GETSAFEPTR(model, ParticleModel, typetag_ParticleModel)
|
||||
__SQ_GETEND
|
||||
if (e->render_data.IsNull())
|
||||
return sq_throwerror(vm, "Emitter has no render data, you need to call ItemRenderSetup() first.");
|
||||
e->render_data->particle_model = model;
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
SQInteger EmitterSetBirthRateScale(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(e, MEmitter, typetag_Emitter)
|
||||
__SQ_GETFLOAT(scale)
|
||||
__SQ_GETEND
|
||||
e->birth_rate_scale = scale;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger EmitterSetBirthSizeScale(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(e, MEmitter, typetag_Emitter)
|
||||
__SQ_GETFLOAT(scale)
|
||||
__SQ_GETEND
|
||||
e->birth_size_scale = scale;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger EmitterSetBirthSpeedScale(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(e, MEmitter, typetag_Emitter)
|
||||
__SQ_GETFLOAT(scale)
|
||||
__SQ_GETEND
|
||||
e->birth_speed_scale = scale;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger EmitterSetBirthOpacityScale(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(e, MEmitter, typetag_Emitter)
|
||||
__SQ_GETFLOAT(scale)
|
||||
__SQ_GETEND
|
||||
e->birth_opacity_scale = scale;
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
void RegisterEmitterBinding(HSQUIRRELVM vm)
|
||||
//--------------------------------------------------------
|
||||
{
|
||||
/*#
|
||||
Topic: Emitter
|
||||
Type: Emitter
|
||||
Type: ParticleModel
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: EmitterSettings
|
||||
Desc: Emitter functions
|
||||
#*/
|
||||
/*#
|
||||
Func: EmitterSetParticleModel
|
||||
Proto: void:Emitter,ParticleModel
|
||||
Desc: Set the emitter particle model.
|
||||
#*/
|
||||
sq_register(vm, EmitterSetParticleModel, "EmitterSetParticleModel", _SC(".xx"));
|
||||
|
||||
/*#
|
||||
Func: EmitterSetBirthRateScale
|
||||
Proto: void:Emitter,float scale
|
||||
Desc: Set the emitter birth rate scale.
|
||||
#*/
|
||||
sq_register(vm, EmitterSetBirthRateScale, "EmitterSetBirthRateScale", _SC(".xn"));
|
||||
/*#
|
||||
Func: EmitterSetBirthSizeScale
|
||||
Proto: void:Emitter,float scale
|
||||
Desc: Set the emitter birth size scale.
|
||||
#*/
|
||||
sq_register(vm, EmitterSetBirthSizeScale, "EmitterSetBirthSizeScale", _SC(".xn"));
|
||||
/*#
|
||||
Func: EmitterSetBirthSpeedScale
|
||||
Proto: void:Emitter,float scale
|
||||
Desc: Set the emitter birth speed scale.
|
||||
#*/
|
||||
sq_register(vm, EmitterSetBirthSpeedScale, "EmitterSetBirthSpeedScale", _SC(".xn"));
|
||||
/*#
|
||||
Func: EmitterSetBirthOpacityScale
|
||||
Proto: void:Emitter,float scale
|
||||
Desc: Set the emitter birth opacity scale.
|
||||
#*/
|
||||
sq_register(vm, EmitterSetBirthOpacityScale, "EmitterSetBirthOpacityScale", _SC(".xn"));
|
||||
}
|
||||
103
include/modules/script_squirrel/legacy/font_binding.cpp
Normal file
103
include/modules/script_squirrel/legacy/font_binding.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "squirrel_binding.h"
|
||||
#include "binding_helpers.h"
|
||||
#include "font/font_renderer.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
void IterateTextParameters(HSQUIRRELVM vm, int idx, TextState &state);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger FontSetFallback(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(font, FontEx, typetag_Font)
|
||||
__SQ_GETSAFEPTR(fbck, FontEx, typetag_Font)
|
||||
__SQ_GETEND
|
||||
font->fallback = fbck;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger FontSetParametersOffset(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(4)
|
||||
__SQ_GETSAFEPTR(font, FontEx, typetag_Font)
|
||||
__SQ_GETFLOAT(size)
|
||||
__SQ_GETFLOAT(tracking)
|
||||
__SQ_GETFLOAT(leading)
|
||||
__SQ_GETEND
|
||||
font->size_multiplier = size;
|
||||
font->tracking_offset = tracking;
|
||||
font->leading_offset = leading;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger FontComputeRect(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(4)
|
||||
__SQ_GETRECT(clip_rect)
|
||||
__SQ_GETSTRING(text)
|
||||
__SQ_GETSAFEPTR(font, FontEx, typetag_Font)
|
||||
|
||||
TextState state;
|
||||
IterateTextParameters(vm, __sq_stackpos, state);
|
||||
__SQ_GETUPDATESTACK
|
||||
|
||||
state.font = font;
|
||||
iRect out_rect = FontRenderer::Format(text, state, clip_rect);
|
||||
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNRECT(out_rect)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterFontBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Font
|
||||
Type: Font
|
||||
Desc: A truetype font that can be used to render to a picture object.
|
||||
Related: Picture,Project
|
||||
#*/
|
||||
/*#
|
||||
Section: FontGeneral
|
||||
Desc: Font Settings
|
||||
#*/
|
||||
/*#
|
||||
Func: FontSetParametersOffset
|
||||
Proto: void:Font,float size_multiplier,float tracking_offset,float leading_offset
|
||||
Desc: Set font-specific properties offset. This function is usually used to normalize font characteristics when porting an application to a different locale.
|
||||
#*/
|
||||
sq_register(vm, FontSetParametersOffset, "FontSetParametersOffset", _SC(".xnnn"));
|
||||
sq_register(vm, FontSetParametersOffset, "UIFontSetParametersOffset", _SC(".xnnn"));
|
||||
/*#
|
||||
Func: FontSetFallback
|
||||
Proto: void:Font font,Font fallback
|
||||
Desc: Set a font to query when a glyph is missing from this font.
|
||||
#*/
|
||||
sq_register(vm, FontSetFallback, "FontSetFallback", _SC(".xx"));
|
||||
sq_register(vm, FontSetFallback, "UIFontSetFallback", _SC(".xx"));
|
||||
/*#
|
||||
Func: FontComputeRect
|
||||
Proto: rect:rect clip_rect,string text,Font font,table param
|
||||
Desc: Compute the bounding rect of a formatted text string, does not perform any graphic output.
|
||||
<br>
|
||||
The following table keys are available:<br>
|
||||
<ul>
|
||||
<li><b>'color'</b>: Hexadecimal RGBA (eg. Red: xff0000ff)
|
||||
<li><b>'align'</b>: TextAlign
|
||||
<li><b>'format'</b>: TextFormat
|
||||
<li><b>'tracking'</b>: Integer value specifying an extra space between glyphs.
|
||||
<li><b>'heading'</b>: Integer value specifying an extra space between lines.
|
||||
</ul>
|
||||
#*/
|
||||
sq_register(vm, FontComputeRect, "FontComputeRect", _SC(".xsxt"));
|
||||
sq_register(vm, FontComputeRect, "UIFontComputeRect", _SC(".xsxt"));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
537
include/modules/script_squirrel/legacy/geometry_binding.cpp
Normal file
537
include/modules/script_squirrel/legacy/geometry_binding.cpp
Normal file
@ -0,0 +1,537 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "core/render_data.h"
|
||||
#include "core/geometry.h"
|
||||
#include "core/iso_surface.h"
|
||||
#include "core/resource_factories.h"
|
||||
#include "core/graphic_resource_factory.h"
|
||||
#include "metafile/nml_object.h"
|
||||
#include "gpu/gpu_material.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Render;
|
||||
using namespace GS::Script;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometrySaveOnItself(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_GETSAFEPTR(f, Core::ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_GETEND
|
||||
|
||||
// get the geo from core
|
||||
GS::Core::Geometry * core_geo = f->graphic->LoadGeometry(g->name);
|
||||
|
||||
core_geo->flag = g->flag;
|
||||
core_geo->lod_distance = g->lod_distance;
|
||||
|
||||
if(g->lod_proxy.IsValid())
|
||||
core_geo->lod_proxy = g->lod_proxy->name;
|
||||
else
|
||||
core_geo->lod_proxy = "";
|
||||
|
||||
if(g->shadow_proxy.IsValid())
|
||||
core_geo->shadow_proxy = g->shadow_proxy->name;
|
||||
else
|
||||
core_geo->shadow_proxy = "";
|
||||
|
||||
bool r = NML::SaveToFile(*core_geo, core_geo->name);
|
||||
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometryGetShadowProxyNull(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_RETURNBOOL(g->flag.IsSet(Core::Geometry::FlagNullShadowProxy))
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometrySetShadowProxyNull(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_GETBOOL(ShadowProxyNull)
|
||||
__SQ_GETEND
|
||||
g->flag.Raise(Core::Geometry::FlagNullShadowProxy, asbool(ShadowProxyNull));
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometryGetLodNull(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_RETURNBOOL(g->flag.IsSet(Core::Geometry::FlagNullLodProxy))
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometrySetLodNull(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_GETBOOL(LodNull)
|
||||
__SQ_GETEND
|
||||
g->flag.Raise(Core::Geometry::FlagNullLodProxy, asbool(LodNull));
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometryGetLodDistance(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_RETURNFLOAT(g->lod_distance)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometrySetLodDistance(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_GETFLOAT(n)
|
||||
__SQ_GETEND
|
||||
g->lod_distance = n;
|
||||
__SQ_RETURN
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometryGetLod(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_RETURNSAFEPTR(g->lod_proxy.c_ptr(), typetag_Geometry)
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometrySetLod(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_GETSAFEPTRALLOWNULL(geo_Lod, GS::Render::Geometry, typetag_Geometry)
|
||||
__SQ_GETEND
|
||||
g->lod_proxy = geo_Lod ? geo_Lod : NULL;
|
||||
__SQ_RETURN
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometryGetShadowProxy(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_RETURNSAFEPTR(g->shadow_proxy.c_ptr(), typetag_Geometry)
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometrySetShadowProxy(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_GETSAFEPTRALLOWNULL(geo_shadow_proxy, GS::Render::Geometry, typetag_Geometry)
|
||||
__SQ_GETEND
|
||||
g->shadow_proxy = geo_shadow_proxy? geo_shadow_proxy : NULL;
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometryGetName(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_RETURNSTRING(g->name)
|
||||
}
|
||||
SQInteger GeometryGetMinMax(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_RETURNMINMAX(g->minmax)
|
||||
}
|
||||
SQInteger GeometrySetHidden(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_GETBOOL(hidden)
|
||||
__SQ_GETEND
|
||||
g->flag.Raise(Core::Geometry::FlagHidden, asbool(hidden));
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger GeometryOptimize(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger GeometryComputeIsoSurface(HSQUIRRELVM vm)
|
||||
{
|
||||
sq_pop(vm, 4);
|
||||
/*
|
||||
__SQ_GETSTART(4)
|
||||
__SQ_GETSAFEPTR(Item, nMItem, typetag_Item)
|
||||
__SQ_GETINT(nb_metaball)
|
||||
|
||||
if ((nb_metaball > 0) && (Item->GetItemType() == Type_Object))
|
||||
{
|
||||
// get the geometry, or if it doesn't have it create one
|
||||
nSharedPtr <nGeometry> g;
|
||||
if(((nMObject *)Item)->GetGeometry().IsNull())
|
||||
{
|
||||
g = new nGeometry(Item->GetScene().GetEngine());
|
||||
((nMObject *)Item)->SetGeometry(g.c_ptr());
|
||||
}
|
||||
else
|
||||
g = ((nMObject *)Item)->GetGeometry();
|
||||
|
||||
nVector* pos_metaball = new nVector[nb_metaball];
|
||||
|
||||
// get the list of metaball
|
||||
sq_pushnull(vm);//null iterator
|
||||
for(int i=0; i<nb_metaball; ++i)
|
||||
{
|
||||
sq_next(vm, __SQ_STACKPOS-1 );
|
||||
GetVector(vm, -1, pos_metaball[i]);
|
||||
sq_pop(vm,2);
|
||||
}
|
||||
sq_pop(vm,1); //pops the null iterator
|
||||
|
||||
__SQ_GETUPDATESTACK
|
||||
|
||||
float* value_metaball = new float[nb_metaball];
|
||||
sq_pushnull(vm);//null iterator
|
||||
for(int i=0; i<nb_metaball; ++i)
|
||||
{
|
||||
sq_next(vm, __SQ_STACKPOS-1 );
|
||||
sq_getfloat(vm, -1, &value_metaball[i]);
|
||||
sq_pop(vm, 2);
|
||||
}
|
||||
sq_pop(vm,1); //pops the null iterator
|
||||
|
||||
__SQ_GETEND
|
||||
|
||||
// compute min max from the metaball
|
||||
nVector MinGrid(10000000.0f,10000000.0f,10000000.0f);
|
||||
nVector MaxGrid(-10000000.0f,-10000000.0f,-10000000.0f);
|
||||
|
||||
for(int i=0; i<nb_metaball; ++i)
|
||||
{
|
||||
if (pos_metaball[i].x+value_metaball[i] > MaxGrid.x) MaxGrid.x = pos_metaball[i].x+value_metaball[i];
|
||||
if (pos_metaball[i].y+value_metaball[i] > MaxGrid.y) MaxGrid.y = pos_metaball[i].y+value_metaball[i];
|
||||
if (pos_metaball[i].z+value_metaball[i] > MaxGrid.z) MaxGrid.z = pos_metaball[i].z+value_metaball[i];
|
||||
if (pos_metaball[i].x-value_metaball[i] < MinGrid.x) MinGrid.x = pos_metaball[i].x-value_metaball[i];
|
||||
if (pos_metaball[i].y-value_metaball[i] < MinGrid.y) MinGrid.y = pos_metaball[i].y-value_metaball[i];
|
||||
if (pos_metaball[i].z-value_metaball[i] < MinGrid.z) MinGrid.z = pos_metaball[i].z-value_metaball[i];
|
||||
}
|
||||
|
||||
nIsosurface isosurface(g->GetEngine());
|
||||
isosurface.Init(MinGrid, MaxGrid-MinGrid, nVector(90, 90, 90));
|
||||
|
||||
g->Free();
|
||||
isosurface.Triangularize(g.c_ptr(), nb_metaball, pos_metaball, value_metaball);
|
||||
g->material_table.Allocate(1);
|
||||
|
||||
nMaterial *m = g->material_table[0] = new nMaterial(g->GetEngine());
|
||||
m->renderword |= nMaterial::Render_Smooth;
|
||||
// m->shader_map = m->AsShaderMap();
|
||||
//g->ComputeVertexToPolygon();
|
||||
// // Update ISO
|
||||
g->render_data = g->GetEngine().GetRenderer().SetupGeometry(g.c_ptr());
|
||||
|
||||
_safe_delete_array(value_metaball);
|
||||
_safe_delete_array(pos_metaball);
|
||||
}
|
||||
*/
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger GeometrySetup(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__LOG_V__ << "GeometrySetup() STUB\n";
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometryGetMaterialList(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(g, Geometry, typetag_Geometry)
|
||||
sq_newarray(vm, 0);
|
||||
|
||||
for (uint n = 0; n < g->material_table.GetCount(); ++n)
|
||||
{
|
||||
CObject::Push(vm, (void *)g->material_table[n].c_ptr(), typetag_Material);
|
||||
sq_arrayappend(vm, -2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
SQInteger GeometryGetMaterialCount(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_RETURNINT(g->material_table.GetCount())
|
||||
}
|
||||
SQInteger GeometryGetMaterial(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_GETSTRING(name)
|
||||
|
||||
Material *m = NULL;
|
||||
for (uint n = 0; n < g->material_table.GetCount(); ++n)
|
||||
if (g->material_table[n]->name == name)
|
||||
{
|
||||
m = g->material_table[n];
|
||||
break;
|
||||
}
|
||||
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(m, typetag_Material)
|
||||
}
|
||||
SQInteger GeometryGetMaterialFromIndex(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_GETINT(index)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(g->material_table[(int)index].c_ptr(), typetag_Material)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometrySetMaterial(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(g, Geometry, typetag_Geometry)
|
||||
__SQ_GETINT(index)
|
||||
__SQ_GETSAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(g->SetMaterial(uint(index), m))
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger GeometryCloneMaterials(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(g, Geometry, typetag_Geometry)
|
||||
|
||||
__LOG_W__ << "[SQ] GeometryCloneMaterials: Cloning all materials for geometry '" << g->name << "'...\n";
|
||||
|
||||
uint mat_count = g->material_table.GetCount();
|
||||
__LOG_W__ << "[SQ] GeometryCloneMaterials: Found " << mat_count << " materials.\n";
|
||||
|
||||
for (uint i = 0; i < mat_count; ++i)
|
||||
{
|
||||
Material *original = g->material_table[i].c_ptr();
|
||||
if (!original)
|
||||
{
|
||||
__LOG_W__ << "[SQ] GeometryCloneMaterials: Material " << i << " is NULL, skipping.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
__LOG_W__ << "[SQ] GeometryCloneMaterials: Cloning material " << i << " ('" << original->name << "')...\n";
|
||||
|
||||
// Cast to GPU::Material
|
||||
GPU::Material *gpu_mat = dynamic_cast<GPU::Material*>(original);
|
||||
if (!gpu_mat)
|
||||
{
|
||||
__LOG_W__ << "[SQ] GeometryCloneMaterials: Material " << i << " is not GPU::Material, skipping.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Clone manually (same as MaterialClone)
|
||||
try
|
||||
{
|
||||
GPU::Renderer &rend = gpu_mat->renderer;
|
||||
Material *cloned = new GPU::Material(rend);
|
||||
|
||||
// Copy properties
|
||||
cloned->name = gpu_mat->name + "_clone";
|
||||
*((Core::BasicMaterial *)cloned) = *((Core::BasicMaterial *)gpu_mat);
|
||||
((GPU::Material*)cloned)->shader = gpu_mat->shader;
|
||||
|
||||
// Copy texture table
|
||||
for (uint n = 0; n < Core::Material::max_texture_stage; ++n)
|
||||
{
|
||||
cloned->texture_table[n] = gpu_mat->texture_table[n];
|
||||
}
|
||||
|
||||
// Assign cloned material back to geometry
|
||||
g->SetMaterial(i, cloned);
|
||||
|
||||
__LOG_W__ << "[SQ] GeometryCloneMaterials: Material " << i << " cloned successfully.\n";
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
__LOG_E__ << "[SQ] GeometryCloneMaterials: Exception while cloning material " << i << "!\n";
|
||||
}
|
||||
}
|
||||
|
||||
__LOG_W__ << "[SQ] GeometryCloneMaterials: Done!\n";
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------
|
||||
void RegisterGeometryBinding(HSQUIRRELVM vm)
|
||||
//-------------------------------------------------
|
||||
{
|
||||
/*#
|
||||
Topic: Geometry
|
||||
Type: Geometry
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: GeometryGeneric
|
||||
Desc: Generic functions
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Func: GeometryGetLod
|
||||
Proto: Geometry:Geometry geo
|
||||
Desc: Get geometry get geometry LOD.
|
||||
#*/
|
||||
sq_register(vm, GeometryGetLod, "GeometryGetLod", _SC(".x"));
|
||||
/*#
|
||||
Func: GeometrySetLod
|
||||
Proto: void:Geometry geo, Geometry geo_LOD
|
||||
Desc: Set geometry LOD.
|
||||
#*/
|
||||
sq_register(vm, GeometrySetLod, "GeometrySetLod", _SC(".xx"));
|
||||
|
||||
/*#
|
||||
Func: GeometryGetShadowProxy
|
||||
Proto: Geometry:Geometry geo
|
||||
Desc: Get geometry get geometry Shadow proxy.
|
||||
#*/
|
||||
sq_register(vm, GeometryGetShadowProxy, "GeometryGetShadowProxy", _SC(".x"));
|
||||
/*#
|
||||
Func: GeometrySetShadowProxy
|
||||
Proto: void:Geometry geo, Geometry show_proxy
|
||||
Desc: Set geometry shadow proxy
|
||||
#*/
|
||||
sq_register(vm, GeometrySetShadowProxy, "GeometrySetShadowProxy", _SC(".xx"));
|
||||
|
||||
/*#
|
||||
Func: GeometryGetLodDistance
|
||||
Proto: float:Geometry geo
|
||||
Desc: Get geometry Lod distance.
|
||||
#*/
|
||||
sq_register(vm, GeometryGetLodDistance, "GeometryGetLodDistance", _SC(".x"));
|
||||
/*#
|
||||
Func: GeometrySetLodDistance
|
||||
Proto: void:Geometry geo, float Lod distance
|
||||
Desc: Set geometry Lod distance
|
||||
#*/
|
||||
sq_register(vm, GeometrySetLodDistance, "GeometrySetLodDistance", _SC(".xn"));
|
||||
|
||||
/*#
|
||||
Func: GeometryGetLodNull
|
||||
Proto: bool:Geometry geo
|
||||
Desc: Get geometry Lod Null.
|
||||
#*/
|
||||
sq_register(vm, GeometryGetLodNull, "GeometryGetLodNull", _SC(".x"));
|
||||
/*#
|
||||
Func: GeometrySetLodNull
|
||||
Proto: void:Geometry geo, bool LodNull
|
||||
Desc: Set geometry Lod Null
|
||||
#*/
|
||||
sq_register(vm, GeometrySetLodNull, "GeometrySetLodNull", _SC(".xb"));
|
||||
/*#
|
||||
Func: GeometryGetShadowProxyNull
|
||||
Proto: bool:Geometry geo
|
||||
Desc: Get geometry ShadowProxy Null.
|
||||
#*/
|
||||
sq_register(vm, GeometryGetShadowProxyNull, "GeometryGetShadowProxyNull", _SC(".x"));
|
||||
/*#
|
||||
Func: GeometrySetShadowProxyNull
|
||||
Proto: void:Geometry geo, bool ShadowProxyNull
|
||||
Desc: Set geometry ShadowProxy Null
|
||||
#*/
|
||||
sq_register(vm, GeometrySetShadowProxyNull, "GeometrySetShadowProxyNull", _SC(".xb"));
|
||||
|
||||
/*#
|
||||
Func: GeometrySaveOnItself
|
||||
Proto: void:Geometry geo, g_factory
|
||||
Desc: Save the geometry on it's own nmg.
|
||||
#*/
|
||||
sq_register(vm, GeometrySaveOnItself, "GeometrySaveOnItself", _SC(".xx"));
|
||||
|
||||
|
||||
/*#
|
||||
Func: GeometryGetName
|
||||
Proto: string:Geometry geo
|
||||
Desc: Get geometry name.
|
||||
#*/
|
||||
sq_register(vm, GeometryGetName, "GeometryGetName", _SC(".x"));
|
||||
/*#
|
||||
Func: GeometrySetHidden
|
||||
Proto: void:Geometry geo,bool hidden
|
||||
Desc: Hide or show geometry, items referring to this geometry will still be updated.
|
||||
#*/
|
||||
sq_register(vm, GeometrySetHidden, "GeometrySetHidden", _SC(".xb"));
|
||||
/*#
|
||||
Func: GeometryOptimize
|
||||
Proto: void:Geometry geo
|
||||
Desc: Optimize geometry for realtime rendering.
|
||||
#*/
|
||||
sq_register(vm, GeometryOptimize, "GeometryOptimize", _SC(".x"));
|
||||
/*#
|
||||
Func: GeometryComputeIsoSurface
|
||||
Proto: void:Item item, int nb_metaball,array pos_metaball,array value_metaball
|
||||
Desc: Create an iso surface to the geometry with the array of metaball.
|
||||
#*/
|
||||
sq_register(vm, GeometryComputeIsoSurface, "GeometryComputeIsoSurface", _SC(".xiaa"));
|
||||
/*#
|
||||
Func: GeometrySetup
|
||||
Proto: void:Geometry geo
|
||||
Desc: Setup geometry in the renderer.
|
||||
#*/
|
||||
sq_register(vm, GeometrySetup, "GeometrySetup", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: GeometryTopology
|
||||
Desc: Topology functions
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Func: GeometryGetMinMax
|
||||
Proto: MinMax:Geometry geo
|
||||
Desc: Get geometry minmax.
|
||||
#*/
|
||||
sq_register(vm, GeometryGetMinMax, "GeometryGetMinMax", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: GeometryMaterial
|
||||
Desc: Material functions
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Func: GeometryGetMaterialList
|
||||
Proto: array:Geometry geo
|
||||
Desc: Return a list of all materials in a geometry.
|
||||
#*/
|
||||
sq_register(vm, GeometryGetMaterialList, "GeometryGetMaterialList", _SC(".x"));
|
||||
/*#
|
||||
Func: GeometryGetMaterialCount
|
||||
Proto: int:Geometry geo
|
||||
Desc: Get geometry material count.
|
||||
#*/
|
||||
sq_register(vm, GeometryGetMaterialCount, "GeometryGetMaterialCount", _SC(".x"));
|
||||
/*#
|
||||
Func: GeometryGetMaterial
|
||||
Proto: Material:Geometry geo,string name
|
||||
Desc: Get material from name.
|
||||
#*/
|
||||
sq_register(vm, GeometryGetMaterial, "GeometryGetMaterial", _SC(".xs"));
|
||||
/*#
|
||||
Func: GeometrySetMaterial
|
||||
Proto: bool:Geometry geo,int index,Material material
|
||||
Desc: Replace a material in the geometry material table.
|
||||
#*/
|
||||
sq_register(vm, GeometrySetMaterial, "GeometrySetMaterial", _SC(".xix"));
|
||||
/*#
|
||||
Func: GeometryCloneMaterials
|
||||
Proto: void:Geometry geo
|
||||
Desc: Clone all materials in the geometry. Each material becomes an independent copy.
|
||||
Note: This allows you to modify materials for one geometry without affecting others that share the same loaded geometry file.
|
||||
Example: GeometryCloneMaterials(geo)
|
||||
#*/
|
||||
sq_register(vm, GeometryCloneMaterials, "GeometryCloneMaterials", _SC(".x"));
|
||||
/*#
|
||||
Func: GeometryGetMaterialFromIndex
|
||||
Proto: Material:Geometry geo,int index
|
||||
Desc: Get material from index.
|
||||
#*/
|
||||
sq_register(vm, GeometryGetMaterialFromIndex, "GeometryGetMaterialFromIndex", _SC(".xi"));
|
||||
}
|
||||
310
include/modules/script_squirrel/legacy/group_binding.cpp
Normal file
310
include/modules/script_squirrel/legacy/group_binding.cpp
Normal file
@ -0,0 +1,310 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "script_squirrel/cobject/matrix_decl.h"
|
||||
#include "scene3d/group.h"
|
||||
#include "automation/automation_source_group.h"
|
||||
#include "math/matrix4.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
SQInteger GroupSetInvisible(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, Group, typetag_Group)
|
||||
__SQ_GETBOOL(value)
|
||||
__SQ_GETEND
|
||||
group->SetInvisible(value ? true : false);
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
extern SQInteger GetMatrix4(HSQUIRRELVM vm, int idx, GS::Matrix4 &mtx);
|
||||
|
||||
SQInteger GroupOffsetMatrix(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, Group, typetag_Group)
|
||||
__SQ_GETMATRIX4(m)
|
||||
__SQ_GETEND
|
||||
group->Offset(m);
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
SQInteger GroupFindItem(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, Group, typetag_Group)
|
||||
__SQ_GETSTRING(item_id)
|
||||
__SQ_GETEND
|
||||
MItem *item = group->Item(item_id);
|
||||
__SQ_RETURNSAFEPTR(item, typetag_Item)
|
||||
}
|
||||
|
||||
SQInteger GroupSetRootItem(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, Group, typetag_Group)
|
||||
__SQ_GETSAFEPTR(root, MItem, typetag_Item)
|
||||
__SQ_GETEND
|
||||
group->SetRootItem(root);
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
SQInteger GroupGetRootItem(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(group, Group, typetag_Group)
|
||||
__SQ_RETURNSAFEPTR(group->GetRootItem(), typetag_Item)
|
||||
}
|
||||
|
||||
SQInteger GroupItemIsMember(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, Group, typetag_Group)
|
||||
__SQ_GETSAFEPTR(item, MItem, typetag_Item)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(group->IsMember(item))
|
||||
}
|
||||
SQInteger GroupAddItem(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, Group, typetag_Group)
|
||||
__SQ_GETSAFEPTR(item, MItem, typetag_Item)
|
||||
__SQ_GETEND
|
||||
group->Add(item);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger GroupRemoveItem(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, Group, typetag_Group)
|
||||
__SQ_GETSAFEPTR(item, MItem, typetag_Item)
|
||||
__SQ_GETEND
|
||||
group->Remove(item);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger GroupSetName(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, Group, typetag_Group)
|
||||
__SQ_GETSTRING(_name)
|
||||
group->name = _name;
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger GroupGetName(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(group, Group, typetag_Group)
|
||||
__SQ_RETURNSTRING(group->name)
|
||||
}
|
||||
|
||||
SQInteger GroupSetup(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(group, Group, typetag_Group)
|
||||
group->Setup();
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
SQInteger GroupSetupScript(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(group, Group, typetag_Group)
|
||||
__LOG_V__ << "GroupSetupScript: STUB\n";
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
SQInteger GroupRenderSetup(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(group, Group, typetag_Group)
|
||||
__SQ_GETSAFEPTR(rf, GS::Core::ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_GETEND
|
||||
group->RenderSetup(rf);
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
SQInteger GroupReset(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(group, Group, typetag_Group)
|
||||
group->Reset();
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
SQInteger GroupSetMotion(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(group, Group, typetag_Group)
|
||||
__SQ_GETSTRING(name)
|
||||
__SQ_GETFLOAT(blend)
|
||||
GS::Automation::SourceGroup *anim_group = NULL;
|
||||
group->SetMotion(name, &anim_group, blend);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNMANAGEDSAFEPTR(anim_group, typetag_AutomationSourceGroup)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
SQInteger GroupGetItemList(HSQUIRRELVM vm)
|
||||
//--------------------------------------------------
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(group, Group, typetag_Group)
|
||||
sq_newarray(vm, 0);
|
||||
ListForeachPtr(MItem *, i, group->GetItemList())
|
||||
{
|
||||
CObject::Push(vm, (void *)i, typetag_Item);
|
||||
sq_arrayappend(vm, -2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
void RegisterGroupBinding(HSQUIRRELVM vm)
|
||||
//----------------------------------------------
|
||||
{
|
||||
/*#
|
||||
Topic: Group
|
||||
Desc: A group holds a reference to several scene items.
|
||||
It is often used to keep track of instantiated 'block scene' items and resources inside a larger scene.
|
||||
Type: Group
|
||||
Related: Scene, Item
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: GroupManagement
|
||||
Desc: Management
|
||||
#*/
|
||||
/*#
|
||||
Func: GroupSetup
|
||||
Proto: void:Group group
|
||||
Desc: Setup all members of a group.
|
||||
See: ItemSetup
|
||||
#*/
|
||||
sq_register(vm, GroupSetup, "GroupSetup", _SC(".x"));
|
||||
/*#
|
||||
Func: GroupSetup
|
||||
Proto: void:Group group
|
||||
Desc: Setup all members of a group.
|
||||
See: ItemSetup
|
||||
#*/
|
||||
sq_register(vm, GroupSetup, "GroupSetup", _SC(".x"));
|
||||
/*#
|
||||
Func: GroupSetupScript
|
||||
Proto: void:Group group
|
||||
Desc: Setup the script object of all members of a group.
|
||||
See: ItemSetupScript
|
||||
#*/
|
||||
sq_register(vm, GroupSetupScript, "GroupSetupScript", _SC(".x"));
|
||||
/*#
|
||||
Func: GroupReset
|
||||
Proto: void:Group group
|
||||
Desc: Reset all members of a group.
|
||||
See: ItemReset
|
||||
#*/
|
||||
sq_register(vm, GroupReset, "GroupReset", _SC(".x"));
|
||||
/*#
|
||||
Func: GroupRenderSetup
|
||||
Proto: void:Group group,ResourceFactory factory
|
||||
Desc: Setup rendering data for all members of a group.
|
||||
Example: GroupRenderSetup(group, g_factory)
|
||||
See: ItemRenderSetup
|
||||
#*/
|
||||
sq_register(vm, GroupRenderSetup, "GroupRenderSetup", _SC(".xx"));
|
||||
|
||||
/*#
|
||||
Func: GroupGetItemList
|
||||
Proto: Array:Group group
|
||||
Desc: Return the group item list.
|
||||
Example:
|
||||
function ListGroupItemNames(group)
|
||||
{
|
||||
local group_name = GroupGetName(group)
|
||||
|
||||
local items = GroupGetItemList(group)
|
||||
foreach (item in items)
|
||||
print("Item " + ItemGetName(item) + " is a member of group" + group_name + ".")
|
||||
}
|
||||
#*/
|
||||
sq_register(vm, GroupGetItemList, "GroupGetItemList", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Func: GroupGetRootItem
|
||||
Proto: Item:Group group
|
||||
Desc: Return the root item of a group.
|
||||
#*/
|
||||
sq_register(vm, GroupGetRootItem, "GroupGetRootItem", _SC(".x"));
|
||||
/*#
|
||||
Func: GroupSetRootItem
|
||||
Proto: void:Group group,Item root_item
|
||||
Desc: Set the root item of a group. All members of a group are linked to its root item if it has one.
|
||||
#*/
|
||||
sq_register(vm, GroupSetRootItem, "GroupSetRootItem", _SC(".xx"));
|
||||
/*#
|
||||
Func: GroupSetInvisible
|
||||
Proto: void:Group group,bool set_invisible
|
||||
Desc: Hide all members of a group.
|
||||
#*/
|
||||
sq_register(vm, GroupSetInvisible, "GroupSetInvisible", _SC(".xb"));
|
||||
/*#
|
||||
Func: GroupFindItem
|
||||
Proto: item:Group group,string name_to_find
|
||||
Desc: Find an item in a group from its name.
|
||||
#*/
|
||||
sq_register(vm, GroupFindItem, "GroupFindItem", _SC(".xs"));
|
||||
/*#
|
||||
Func: GroupItemIsMember
|
||||
Proto: bool:Group group,Item item_to_test
|
||||
Desc: Returns true if item the belongs to the group, false otherwise.
|
||||
#*/
|
||||
sq_register(vm, GroupItemIsMember, "GroupItemIsMember", _SC(".xx"));
|
||||
/*#
|
||||
Func: GroupAddItem
|
||||
Proto: void:Group group,Item item_to_add
|
||||
Desc: Add an item to a group.
|
||||
#*/
|
||||
sq_register(vm, GroupAddItem, "GroupAddItem", _SC(".xx"));
|
||||
/*#
|
||||
Func: GroupRemoveItem
|
||||
Proto: void:Group group,Item item_to_remove
|
||||
Desc: Remove an item from a group.
|
||||
#*/
|
||||
sq_register(vm, GroupRemoveItem, "GroupRemoveItem", _SC(".xx"));
|
||||
/*#
|
||||
Func: GroupSetName
|
||||
Proto: void:Group group,string name
|
||||
Desc: Set the name of a group.
|
||||
#*/
|
||||
sq_register(vm, GroupSetName, "GroupSetName", _SC(".xs"));
|
||||
/*#
|
||||
Func: GroupGetName
|
||||
Proto: string:Group group
|
||||
Desc: Get the name of a group.
|
||||
#*/
|
||||
sq_register(vm, GroupGetName, "GroupGetName", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: GroupTransform
|
||||
Desc: Transformation
|
||||
#*/
|
||||
/*#
|
||||
Func: GroupOffsetMatrix
|
||||
Proto: void:Group group,matrix4 offset_matrix
|
||||
Desc: Apply a 4x4 offset matrix to all group members.
|
||||
See: TransformationMatrix
|
||||
#*/
|
||||
sq_register(vm, GroupOffsetMatrix, "GroupOffsetMatrix", _SC(".xx"));
|
||||
|
||||
/*#
|
||||
Section: GroupMotion
|
||||
Desc: Motion
|
||||
#*/
|
||||
/*#
|
||||
Func: GroupSetMotion
|
||||
Proto: AnimationSourceGroup:Group group,string motion_name,float blend
|
||||
Desc: Set motion on all group items, specify the blend duration, stop all current animation sources.
|
||||
See: ItemSetMotion
|
||||
#*/
|
||||
sq_register(vm, GroupSetMotion, "GroupSetMotion", _SC(".xsn"));
|
||||
}
|
||||
67
include/modules/script_squirrel/legacy/hash_binding.cpp
Normal file
67
include/modules/script_squirrel/legacy/hash_binding.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "hash/md5.h"
|
||||
#include "hash/nsha1.h"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MD5(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(source)
|
||||
|
||||
using namespace GS::MD5;
|
||||
|
||||
Digest md5;
|
||||
|
||||
md5_byte_t digest[16];
|
||||
md5.Append((const md5_byte_t *)source, GS::String::strlen(source));
|
||||
md5.Finish(digest);
|
||||
|
||||
char md5_string[33];
|
||||
DigestToString(digest, md5_string);
|
||||
md5_string[32] = 0;
|
||||
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSTRING(md5_string)
|
||||
}
|
||||
SQInteger SHA1(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(source)
|
||||
GS::String hash = GS::SHA1::ComputeHexa(source);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSTRING(hash.c_str())
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void RegisterHashBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
using namespace GS::Script;
|
||||
|
||||
/*#
|
||||
Topic: Hash
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: Hashing
|
||||
Desc: Hashing
|
||||
#*/
|
||||
/*#
|
||||
Func: MD5
|
||||
Proto: String:String source
|
||||
Desc: Compute a MD5 hexadecimal hash.
|
||||
#*/
|
||||
sq_register(vm, MD5, "MD5", _SC(".s"));
|
||||
/*#
|
||||
Func: SHA1
|
||||
Proto: String:String source
|
||||
Desc: Compute a SHA1 hexadecimal hash.
|
||||
#*/
|
||||
sq_register(vm, SHA1, "SHA1", _SC(".s"));
|
||||
}
|
||||
169
include/modules/script_squirrel/legacy/http_binding.cpp
Normal file
169
include/modules/script_squirrel/legacy/http_binding.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "http_curl/http_curl.h"
|
||||
#include "script_squirrel/legacy/squirrel_binding.h"
|
||||
#include "script/script_variant.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
#if __PLATFORM_EMSCRIPTEN__
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger HttpPost(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger HttpUpdate(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#else
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
class SquirrelHTTP : public HTTP::Curl
|
||||
{
|
||||
HSQUIRRELVM vm;
|
||||
|
||||
public:
|
||||
|
||||
void OnRequestComplete(int ticket_id, const Array <char> &data)
|
||||
{
|
||||
SquirrelVM *sq_vm = GetVMObject(vm);
|
||||
|
||||
if (sq_vm->SetupFunctionCall("OnHttpRequestComplete"))
|
||||
{
|
||||
sq_vm->PushArgument(ticket_id);
|
||||
|
||||
if (data.GetSize() > 0)
|
||||
{
|
||||
String str(data.c_ptr(), data.GetCount());
|
||||
sq_vm->PushArgument(str.c_str());
|
||||
}
|
||||
else
|
||||
sq_vm->PushNullArgument();
|
||||
|
||||
sq_vm->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
void OnRequestError(int ticket_id)
|
||||
{
|
||||
SquirrelVM *sq_vm = GetVMObject(vm);
|
||||
|
||||
if (sq_vm->SetupFunctionCall("OnHttpRequestError"))
|
||||
{
|
||||
sq_vm->PushArgument(ticket_id);
|
||||
sq_vm->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
|
||||
SquirrelHTTP(HSQUIRRELVM v) : vm(v) {}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger HttpPost(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSTRING(url)
|
||||
__SQ_GETSTRING(post)
|
||||
SquirrelVM *sq_vm = GetVMObject(vm);
|
||||
int id = sq_vm->http->Post(url, post);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNINT(id)
|
||||
}
|
||||
SQInteger HttpUpdate(HSQUIRRELVM vm)
|
||||
{
|
||||
SquirrelVM *sq_vm = GetVMObject(vm);
|
||||
sq_vm->http->Update();
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
//#include <iostream.h>
|
||||
#include <winsock.h>
|
||||
SQInteger GetIp(HSQUIRRELVM vm)
|
||||
{
|
||||
String ip_adress;
|
||||
|
||||
char ac[80];
|
||||
if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) {
|
||||
__SQ_RETURNSTRING("");
|
||||
}
|
||||
struct hostent *phe = gethostbyname(ac);
|
||||
if (phe == 0) {
|
||||
__SQ_RETURNSTRING("");
|
||||
}
|
||||
|
||||
for (int i = 0; phe->h_addr_list[i] != 0; ++i) {
|
||||
struct in_addr addr;
|
||||
memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr));
|
||||
ip_adress += String(inet_ntoa(addr)) + String(" ");
|
||||
}
|
||||
|
||||
__SQ_RETURNSTRING(ip_adress.c_str())
|
||||
}
|
||||
//*********************************************************
|
||||
|
||||
#endif
|
||||
|
||||
void RegisterHTTPBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
#if __PLATFORM_EMSCRIPTEN__ == 0
|
||||
SquirrelVM *sq_vm = GetVMObject(vm);
|
||||
sq_vm->http = new SquirrelHTTP(vm);
|
||||
#endif
|
||||
|
||||
/*#
|
||||
Topic: HTTP
|
||||
Desc: Send HTTP POST request to a remote URL and receive remote response asynchronously.
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: HTTP helper
|
||||
Desc: HTTP helper functions.
|
||||
#*/
|
||||
/*#
|
||||
Func: HttpUpdate
|
||||
Proto: void:
|
||||
Desc: Update the HTTP subsystem. You must call this function to receive queued events.
|
||||
See: HttpPost
|
||||
#*/
|
||||
sq_register(vm, HttpUpdate, "HttpUpdate", _SC("."));
|
||||
/*#
|
||||
Func: HttpPost
|
||||
Proto: int:String url, String post
|
||||
Desc: POST an HTTP request to a remote URL and returns the request identifier.<br>This function returns immediately, the request result will be sent to the global HTTP script callbacks.
|
||||
Example:
|
||||
// POST a request with two parameters to a remote server.
|
||||
local id = HttpPost("http://www.someurl.com", "param_a=1&param_b=2")
|
||||
print("HTTP request posted, id: " + id)
|
||||
|
||||
// The two global HTTP request callbacks.
|
||||
function OnHttpRequestComplete(ticket_id, data)
|
||||
{
|
||||
print("HTTP request " + ticket_id + " complete.")
|
||||
print("Data received: " + data)
|
||||
}
|
||||
function OnHttpRequestError(ticket_id)
|
||||
{
|
||||
print("HTTP request " + ticket_id + " errored.")
|
||||
}
|
||||
#*/
|
||||
sq_register(vm, HttpPost, "HttpPost", _SC(".ss"));
|
||||
|
||||
|
||||
/*#
|
||||
Func: GetIp
|
||||
Proto: string:void
|
||||
Desc: Get local ip.
|
||||
#*/
|
||||
sq_register(vm, GetIp, "GetIp", _SC("."));
|
||||
}
|
||||
63
include/modules/script_squirrel/legacy/instance_binding.cpp
Normal file
63
include/modules/script_squirrel/legacy/instance_binding.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "scene3d/instance.h"
|
||||
#include "scene3d/group.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger InstanceGetItemList(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(instance, Instance, typetag_Instance)
|
||||
sq_newarray(vm, 0);
|
||||
if (instance->instance_group)
|
||||
ListForeachPtr(MItem *, i, instance->instance_group->GetItemList())
|
||||
{
|
||||
CObject::Push(vm, (void *)i, typetag_Item);
|
||||
sq_arrayappend(vm, -2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
SQInteger InstanceGetTemplatePath(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(instance, Instance, typetag_Instance)
|
||||
__SQ_RETURNSTRING(instance->template_path.c_str())
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterInstanceBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Instance
|
||||
Type: Instance
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: InstanceGeneric
|
||||
Desc: Generic functions
|
||||
#*/
|
||||
/*#
|
||||
Func: InstanceGetItemList
|
||||
Proto: array:Instance
|
||||
Desc: Return instance item list. Note: The instance must have been instantiate to return any item.
|
||||
#*/
|
||||
sq_register(vm, InstanceGetItemList, "InstanceGetItemList", _SC(".x"));
|
||||
/*#
|
||||
Func: InstanceGetTemplatePath
|
||||
Proto: string:Instance
|
||||
Desc: Return instance path
|
||||
#*/
|
||||
sq_register(vm, InstanceGetTemplatePath, "InstanceGetTemplatePath", _SC(".x"));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
1072
include/modules/script_squirrel/legacy/io_binding.cpp
Normal file
1072
include/modules/script_squirrel/legacy/io_binding.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2455
include/modules/script_squirrel/legacy/item_binding.cpp
Normal file
2455
include/modules/script_squirrel/legacy/item_binding.cpp
Normal file
File diff suppressed because it is too large
Load Diff
347
include/modules/script_squirrel/legacy/light_binding.cpp
Normal file
347
include/modules/script_squirrel/legacy/light_binding.cpp
Normal file
@ -0,0 +1,347 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "scene3d/mlight.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
static CObjectType light_derived_types[] = { typetag_Item, typetag_Light, typetag_Undefined };
|
||||
|
||||
SQInteger LightGetDiffuseIntensity(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(l, MLight, light_derived_types))
|
||||
__SQ_RETURNFLOAT(l->diffuse_intensity)
|
||||
}
|
||||
|
||||
SQInteger LightSetProjectionTexture(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(l, MLight, light_derived_types)
|
||||
__SQ_GETSAFEPTR(t, GS::Render::Texture, typetag_Texture)
|
||||
l->render_data->projection_texture = t;
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger LightSetDiffuseIntensity(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(l, MLight, light_derived_types)
|
||||
__SQ_GETFLOAT(i)
|
||||
__SQ_GETEND
|
||||
l->diffuse_intensity = i;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger LightGetDiffuseColor(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(l, MLight, light_derived_types))
|
||||
__SQ_RETURNVECTOR(l->diffuse_color)
|
||||
}
|
||||
SQInteger LightSetDiffuseColor(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(l, MLight, light_derived_types)
|
||||
__SQ_GETVECTOR(color)
|
||||
__SQ_GETEND
|
||||
l->diffuse_color = color;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger LightGetSpecularIntensity(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(l, MLight, light_derived_types))
|
||||
__SQ_RETURNFLOAT(l->specular_intensity)
|
||||
}
|
||||
SQInteger LightSetSpecularIntensity(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(l, MLight, light_derived_types)
|
||||
__SQ_GETFLOAT(i)
|
||||
__SQ_GETEND
|
||||
l->specular_intensity = i;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger LightGetSpecularColor(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(l, MLight, light_derived_types))
|
||||
__SQ_RETURNVECTOR(l->specular_color)
|
||||
}
|
||||
SQInteger LightSetSpecularColor(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(l, MLight, light_derived_types)
|
||||
__SQ_GETVECTOR(color)
|
||||
__SQ_GETEND
|
||||
l->specular_color = color;
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger LightSetConeAngle(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(l, MLight, light_derived_types)
|
||||
__SQ_GETFLOAT(angle)
|
||||
__SQ_GETEND
|
||||
l->cone_angle = angle;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger LightGetConeAngle(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(l, MLight, light_derived_types))
|
||||
__SQ_RETURNFLOAT(l->cone_angle)
|
||||
}
|
||||
SQInteger LightSetEdgeAngle(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(l, MLight, light_derived_types)
|
||||
__SQ_GETFLOAT(angle)
|
||||
__SQ_GETEND
|
||||
l->edge_angle = angle;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger LightGetEdgeAngle(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(l, MLight, light_derived_types))
|
||||
__SQ_RETURNFLOAT(l->edge_angle)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger LightSetRange(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(l, MLight, light_derived_types)
|
||||
__SQ_GETFLOAT(range)
|
||||
__SQ_GETEND
|
||||
l->range = range;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger LightGetRange(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(l, MLight, light_derived_types))
|
||||
__SQ_RETURNFLOAT(l->range)
|
||||
}
|
||||
SQInteger LightSetShadowRange(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(l, MLight, light_derived_types)
|
||||
__SQ_GETFLOAT(shadow_range)
|
||||
__SQ_GETEND
|
||||
l->shadow_range = shadow_range;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger LightGetShadowRange(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(l, MLight, light_derived_types))
|
||||
__SQ_RETURNFLOAT(l->shadow_range)
|
||||
}
|
||||
SQInteger LightSetVolumeRange(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(l, MLight, light_derived_types)
|
||||
__SQ_GETFLOAT(range)
|
||||
__SQ_GETEND
|
||||
l->volume_range = range;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger LightGetVolumeRange(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(l, MLight, light_derived_types))
|
||||
__SQ_RETURNFLOAT(l->volume_range)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
SQInteger LightGetItem(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(l, MLight, light_derived_types))
|
||||
__SQ_RETURNSAFEPTR((MItem *)l, typetag_Item)
|
||||
}
|
||||
SQInteger LightGetType(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(l, MLight, light_derived_types))
|
||||
__SQ_RETURNINT(l->model)
|
||||
}
|
||||
SQInteger LightSetType(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(l, MLight, light_derived_types)
|
||||
__SQ_GETINT(_type)
|
||||
__SQ_GETEND
|
||||
l->model = (GS::Core::Light::Model)_type;
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterLightBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Light
|
||||
Type: Light
|
||||
Related: Item
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: LightColor
|
||||
Desc: Light color functions
|
||||
#*/
|
||||
/*#
|
||||
Func: LightGetDiffuseIntensity
|
||||
Proto: float:Light
|
||||
Desc: Get light diffuse intensity.
|
||||
#*/
|
||||
sq_register(vm, LightGetDiffuseIntensity, "LightGetDiffuseIntensity", _SC(".x"));
|
||||
/*#
|
||||
Func: LightGetDiffuseColor
|
||||
Proto: Vector:Light
|
||||
Desc: Get light diffuse color.
|
||||
#*/
|
||||
sq_register(vm, LightGetDiffuseColor, "LightGetDiffuseColor", _SC(".x"));
|
||||
/*#
|
||||
Func: LightSetDiffuseIntensity
|
||||
Proto: void:Light,float intensity
|
||||
Desc: Set light diffuse intensity.
|
||||
#*/
|
||||
sq_register(vm, LightSetDiffuseIntensity, "LightSetDiffuseIntensity", _SC(".xn"));
|
||||
/*#
|
||||
Func: LightSetDiffuseColor
|
||||
Proto: void:Light,Vector color
|
||||
Desc: Set light diffuse color.
|
||||
#*/
|
||||
sq_register(vm, LightSetDiffuseColor, "LightSetDiffuseColor", _SC(".xx"));
|
||||
/*#
|
||||
Func: LightGetSpecularIntensity
|
||||
Proto: float:Light
|
||||
Desc: Get light specular intensity.
|
||||
#*/
|
||||
sq_register(vm, LightGetSpecularIntensity, "LightGetSpecularIntensity", _SC(".x"));
|
||||
/*#
|
||||
Func: LightGetSpecularColor
|
||||
Proto: Vector:Light
|
||||
Desc: Get light specular color.
|
||||
#*/
|
||||
sq_register(vm, LightGetSpecularColor, "LightGetSpecularColor", _SC(".x"));
|
||||
/*#
|
||||
Func: LightSetSpecularIntensity
|
||||
Proto: void:Light,float intensity
|
||||
Desc: Set light specular intensity.
|
||||
#*/
|
||||
sq_register(vm, LightSetSpecularIntensity, "LightSetSpecularIntensity", _SC(".xn"));
|
||||
/*#
|
||||
Func: LightSetSpecularColor
|
||||
Proto: void:Light,Vector color
|
||||
Desc: Set light specular color.
|
||||
#*/
|
||||
sq_register(vm, LightSetSpecularColor, "LightSetSpecularColor", _SC(".xx"));
|
||||
|
||||
/*#
|
||||
Section: LightSpot
|
||||
Desc: Spot functions
|
||||
#*/
|
||||
/*#
|
||||
Func: LightSetConeAngle
|
||||
Proto: void:Light,float angle
|
||||
Desc: Set light cone angle in radian, the cone angle is the spot area where intensity is at its maximum.
|
||||
#*/
|
||||
sq_register(vm, LightSetConeAngle, "LightSetConeAngle", _SC(".xn"));
|
||||
/*#
|
||||
Func: LightSetEdgeAngle
|
||||
Proto: void:Light,float angle
|
||||
Desc: Set light edge angle in radian, the edge angle is the spot area where intensity decreases from its maximum toward zero.
|
||||
#*/
|
||||
sq_register(vm, LightSetEdgeAngle, "LightSetEdgeAngle", _SC(".xn"));
|
||||
/*#
|
||||
Func: LightGetConeAngle
|
||||
Proto: float:Light
|
||||
Desc: Get light cone angle in radian.
|
||||
#*/
|
||||
sq_register(vm, LightGetConeAngle, "LightGetConeAngle", _SC(".x"));
|
||||
/*#
|
||||
Func: LightGetEdgeAngle
|
||||
Proto: float:Light
|
||||
Desc: Get light edge angle in radian.
|
||||
#*/
|
||||
sq_register(vm, LightGetEdgeAngle, "LightGetEdgeAngle", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: LightGeneric
|
||||
Desc: Generic functions
|
||||
#*/
|
||||
/*#
|
||||
Func: LightSetRange
|
||||
Proto: void:Light,float range
|
||||
Desc: Set the light range in meter.
|
||||
#*/
|
||||
sq_register(vm, LightSetRange, "LightSetRange", _SC(".xn"));
|
||||
/*#
|
||||
Func: LightGetRange
|
||||
Proto: float:Light
|
||||
Desc: Return the light range in meter.
|
||||
#*/
|
||||
sq_register(vm, LightGetRange, "LightGetRange", _SC(".x"));
|
||||
/*#
|
||||
Func: LightSetShadowRange
|
||||
Proto: void:Light,float range
|
||||
Desc: Set the light range in meter.
|
||||
#*/
|
||||
sq_register(vm, LightSetShadowRange, "LightSetShadowRange", _SC(".xn"));
|
||||
/*#
|
||||
Func: LightGetRange
|
||||
Proto: float:Light
|
||||
Desc: Return the light range in meter.
|
||||
#*/
|
||||
sq_register(vm, LightGetShadowRange, "LightGetShadowRange", _SC(".x"));
|
||||
/*#
|
||||
Func: LightSetVolumeRange
|
||||
Proto: void:Light,float range
|
||||
Desc: Set the light volume range in meter. The volume range has no relation with the volumetric system and is only a performance hint used by some renderer. If unsure this value should be kept equal to the light range.
|
||||
#*/
|
||||
sq_register(vm, LightSetVolumeRange, "LightSetVolumeRange", _SC(".xn"));
|
||||
/*#
|
||||
Func: LightGetVolumeRange
|
||||
Proto: float:Light
|
||||
Desc: Return the light volume range in meter.
|
||||
#*/
|
||||
sq_register(vm, LightGetVolumeRange, "LightGetVolumeRange", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Func: LightSetProjectionTexture
|
||||
Proto: void:Light,Texture
|
||||
Desc: Set light projection texture.
|
||||
#*/
|
||||
sq_register(vm, LightSetProjectionTexture, "LightSetProjectionTexture", _SC(".xx"));
|
||||
/*#
|
||||
Func: LightGetItem
|
||||
Proto: Item:Light
|
||||
Desc: Get light item.
|
||||
#*/
|
||||
sq_register(vm, LightGetItem, "LightGetItem", _SC(".x"));
|
||||
/*#
|
||||
Func: LightGetType
|
||||
Proto: LightType:Light
|
||||
Desc: Get light type.
|
||||
#*/
|
||||
sq_register(vm, LightGetType, "LightGetType", _SC(".x"));
|
||||
/*#
|
||||
Func: LightSetType
|
||||
Proto: void:Light,LightType type
|
||||
Desc: Set light type.
|
||||
#*/
|
||||
sq_register(vm, LightSetType, "LightSetType", _SC(".xi"));
|
||||
|
||||
/*#
|
||||
Enum: LightType
|
||||
Values: LightTypeNone,LightTypeSpot,LightTypeLinear,LightTypePoint
|
||||
#*/
|
||||
using GS::Core::Light;
|
||||
|
||||
sq_pushstring(vm, "LightTypeNone", -1); sq_pushinteger(vm, Light::Model_None); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "LightTypeSpot", -1); sq_pushinteger(vm, Light::Model_Spot); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "LightTypeLinear", -1); sq_pushinteger(vm, Light::Model_Linear); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "LightTypePoint", -1); sq_pushinteger(vm, Light::Model_Point); sq_newslot(vm, -3, true);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
532
include/modules/script_squirrel/legacy/material_binding.cpp
Normal file
532
include/modules/script_squirrel/legacy/material_binding.cpp
Normal file
@ -0,0 +1,532 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "core/material_to_shader_tree.h"
|
||||
#include "core/render_data.h"
|
||||
#include "gpu/gpu_material.h"
|
||||
|
||||
using namespace GS::Render;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MaterialGetDiffuse(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_RETURNVECTORW(m->diffuse)
|
||||
}
|
||||
SQInteger MaterialSetDiffuse(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_GETVECTORW(c)
|
||||
__SQ_GETEND
|
||||
m->diffuse = c;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MaterialGetSpecular(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_RETURNVECTORW(m->specular)
|
||||
}
|
||||
SQInteger MaterialSetSpecular(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_GETVECTORW(c)
|
||||
__SQ_GETEND
|
||||
m->specular = c;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MaterialGetSelf(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_RETURNVECTORW(m->self)
|
||||
}
|
||||
SQInteger MaterialSetSelf(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_GETVECTORW(c)
|
||||
__SQ_GETEND
|
||||
m->self = c;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MaterialGetAmbient(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_RETURNVECTORW(m->ambient)
|
||||
}
|
||||
SQInteger MaterialSetAmbient(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_GETVECTORW(c)
|
||||
__SQ_GETEND
|
||||
m->ambient = c;
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MaterialGetGlossiness(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_RETURNFLOAT(m->glossiness)
|
||||
}
|
||||
SQInteger MaterialSetGlossiness(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_GETFLOAT(v)
|
||||
__SQ_GETEND
|
||||
m->glossiness = v;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MaterialGetOpacity(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_RETURNFLOAT(m->opacity)
|
||||
}
|
||||
SQInteger MaterialSetOpacity(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_GETFLOAT(v)
|
||||
__SQ_GETEND
|
||||
m->opacity = v;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MaterialGetAlphaThreshold(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_RETURNFLOAT(m->athreshold)
|
||||
}
|
||||
SQInteger MaterialSetAlphaThreshold(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_GETFLOAT(v)
|
||||
__SQ_GETEND
|
||||
m->athreshold = v;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MaterialGetDepthBias(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_RETURNFLOAT(m->depth_bias)
|
||||
}
|
||||
SQInteger MaterialSetDepthBias(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(m, Material, typetag_Material)
|
||||
__SQ_GETFLOAT(v)
|
||||
__SQ_GETEND
|
||||
m->depth_bias = v;
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MaterialGetName(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(mat, Material, typetag_Material)
|
||||
__SQ_RETURNSTRING(mat->name.c_str())
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MaterialFlagGet(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mat, Material, typetag_Material)
|
||||
__SQ_GETINT(flag)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(asbool(mat->renderword & flag))
|
||||
}
|
||||
SQInteger MaterialFlagSet(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(mat, Material, typetag_Material)
|
||||
__SQ_GETINT(flag)
|
||||
__SQ_GETBOOL(state)
|
||||
__SQ_GETEND
|
||||
if (state)
|
||||
mat->renderword |= flag;
|
||||
else mat->renderword &= ~flag;
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MaterialGetBlendOperator(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(mat, Material, typetag_Material)
|
||||
__SQ_RETURNINT(mat->blendop)
|
||||
}
|
||||
SQInteger MaterialSetBlendOperator(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mat, Material, typetag_Material)
|
||||
__SQ_GETINT(op)
|
||||
__SQ_GETEND
|
||||
mat->blendop = op;
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MaterialGetTexture(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mat, Material, typetag_Material)
|
||||
__SQ_GETINT(slot)
|
||||
__SQ_GETEND
|
||||
if ((slot < 0) || (slot >= GS::Core::Material::max_texture_stage))
|
||||
return sq_throwerror(vm, "Invalid material texture slot index.");
|
||||
__SQ_RETURNSAFEPTR(mat->texture_table[slot].c_ptr(), typetag_Texture)
|
||||
}
|
||||
SQInteger MaterialSetTexture(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(mat, Material, typetag_Material)
|
||||
__SQ_GETINT(slot)
|
||||
__SQ_GETSAFEPTR(tex, Texture, typetag_Texture)
|
||||
__SQ_GETEND
|
||||
if ((slot < 0) || (slot >= GS::Core::Material::max_texture_stage))
|
||||
return sq_throwerror(vm, "Invalid material texture slot index.");
|
||||
mat->texture_table[slot] = tex;
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MaterialClone(HSQUIRRELVM vm)
|
||||
{
|
||||
__LOG_W__ << "[SQ] MaterialClone: Called from Squirrel.\n";
|
||||
|
||||
__SQ_GETSINGLESAFEPTR(mat, Material, typetag_Material)
|
||||
|
||||
__LOG_W__ << "[SQ] MaterialClone: Got material pointer: " << (void*)mat << "\n";
|
||||
|
||||
if (!mat)
|
||||
{
|
||||
__LOG_E__ << "[SQ] MaterialClone: Input material is NULL!\n";
|
||||
return sq_throwerror(vm, "Input material is NULL");
|
||||
}
|
||||
|
||||
__LOG_W__ << "[SQ] MaterialClone: Material name: '" << mat->name << "'\n";
|
||||
__LOG_W__ << "[SQ] MaterialClone: Material refcount: " << mat->GetRefCount() << "\n";
|
||||
|
||||
// Cast to GPU::Material to ensure we're working with the right type
|
||||
__LOG_W__ << "[SQ] MaterialClone: Attempting dynamic_cast to GPU::Material...\n";
|
||||
GS::GPU::Material *gpu_mat = dynamic_cast<GS::GPU::Material*>(mat);
|
||||
|
||||
if (!gpu_mat)
|
||||
{
|
||||
__LOG_E__ << "[SQ] MaterialClone: Material is not a GPU::Material! Cannot clone.\n";
|
||||
return sq_throwerror(vm, "Material type not supported for cloning");
|
||||
}
|
||||
|
||||
__LOG_W__ << "[SQ] MaterialClone: dynamic_cast succeeded, got GPU::Material at " << (void*)gpu_mat << "\n";
|
||||
|
||||
// WORKAROUND: Clone manually without calling virtual methods
|
||||
// (calling virtual methods crashes for unknown reason)
|
||||
__LOG_W__ << "[SQ] MaterialClone: Cloning manually (bypassing virtual Clone())...\n";
|
||||
|
||||
Material *cloned = NULL;
|
||||
|
||||
try
|
||||
{
|
||||
__LOG_W__ << "[SQ] MaterialClone: Accessing renderer reference...\n";
|
||||
GS::GPU::Renderer &rend = gpu_mat->renderer;
|
||||
__LOG_W__ << "[SQ] MaterialClone: Renderer at: " << (void*)&rend << "\n";
|
||||
|
||||
__LOG_W__ << "[SQ] MaterialClone: Allocating new GPU::Material...\n";
|
||||
cloned = new GS::GPU::Material(rend);
|
||||
__LOG_W__ << "[SQ] MaterialClone: Allocation succeeded: " << (void*)cloned << "\n";
|
||||
|
||||
// Copy properties manually
|
||||
__LOG_W__ << "[SQ] MaterialClone: Copying name...\n";
|
||||
cloned->name = gpu_mat->name + "_clone";
|
||||
|
||||
__LOG_W__ << "[SQ] MaterialClone: Copying BasicMaterial properties...\n";
|
||||
*((GS::Core::BasicMaterial *)cloned) = *((GS::Core::BasicMaterial *)gpu_mat);
|
||||
|
||||
__LOG_W__ << "[SQ] MaterialClone: Copying shader reference...\n";
|
||||
((GS::GPU::Material*)cloned)->shader = gpu_mat->shader;
|
||||
|
||||
__LOG_W__ << "[SQ] MaterialClone: Copying texture table...\n";
|
||||
for (uint n = 0; n < GS::Core::Material::max_texture_stage; ++n)
|
||||
{
|
||||
cloned->texture_table[n] = gpu_mat->texture_table[n];
|
||||
}
|
||||
|
||||
__LOG_W__ << "[SQ] MaterialClone: Manual clone complete!\n";
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
__LOG_E__ << "[SQ] MaterialClone: EXCEPTION caught during manual clone!\n";
|
||||
if (cloned)
|
||||
delete cloned;
|
||||
return sq_throwerror(vm, "Exception during clone");
|
||||
}
|
||||
|
||||
__LOG_W__ << "[SQ] MaterialClone: Clone() returned: " << (void*)cloned << "\n";
|
||||
|
||||
if (!cloned)
|
||||
{
|
||||
__LOG_E__ << "[SQ] MaterialClone: Clone() returned NULL!\n";
|
||||
return sq_throwerror(vm, "Failed to clone material");
|
||||
}
|
||||
|
||||
__LOG_W__ << "[SQ] MaterialClone: Returning managed pointer to Squirrel...\n";
|
||||
// Use managed pointer so Squirrel will handle the reference counting
|
||||
__SQ_RETURNMANAGEDSAFEPTR(cloned, typetag_Material)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MaterialGetShader(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(mat, Material, typetag_Material)
|
||||
__SQ_RETURNSAFEPTR(mat->GetShader(), typetag_MaterialShader)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterMaterialBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Material
|
||||
Type: Material
|
||||
Type: MaterialShader
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: MaterialRenderAttributes
|
||||
Desc: Render attributes functions
|
||||
#*/
|
||||
/*#
|
||||
Func: MaterialGetDiffuse
|
||||
Proto: Vector:Material material
|
||||
Desc: Get material diffuse color.
|
||||
#*/
|
||||
sq_register(vm, MaterialGetDiffuse, "MaterialGetDiffuse", _SC(".x"));
|
||||
/*#
|
||||
Func: MaterialSetDiffuse
|
||||
Proto: void:Material material,Vector diffuse_color
|
||||
Desc: Set material diffuse color.
|
||||
#*/
|
||||
sq_register(vm, MaterialSetDiffuse, "MaterialSetDiffuse", _SC(".xx"));
|
||||
/*#
|
||||
Func: MaterialGetSpecular
|
||||
Proto: Vector:Material material
|
||||
Desc: Get material specular color.
|
||||
#*/
|
||||
sq_register(vm, MaterialGetSpecular, "MaterialGetSpecular", _SC(".x"));
|
||||
/*#
|
||||
Func: MaterialSetSpecular
|
||||
Proto: void:Material material,Vector specular_color
|
||||
Desc: Set material specular color.
|
||||
Note: This value is combined with the light source own specular color and intensity.
|
||||
#*/
|
||||
sq_register(vm, MaterialSetSpecular, "MaterialSetSpecular", _SC(".xx"));
|
||||
/*#
|
||||
Func: MaterialGetSelf
|
||||
Proto: Vector:Material material
|
||||
Desc: Get material self color.
|
||||
#*/
|
||||
sq_register(vm, MaterialGetSelf, "MaterialGetSelf", _SC(".x"));
|
||||
/*#
|
||||
Func: MaterialSetSelf
|
||||
Proto: void:Material material,Vector self_color
|
||||
Desc: Set material self color.
|
||||
#*/
|
||||
sq_register(vm, MaterialSetSelf, "MaterialSetSelf", _SC(".xx"));
|
||||
/*#
|
||||
Func: MaterialGetAmbient
|
||||
Proto: Vector:Material material
|
||||
Desc: Get material ambient color.
|
||||
#*/
|
||||
sq_register(vm, MaterialGetAmbient, "MaterialGetAmbient", _SC(".x"));
|
||||
/*#
|
||||
Func: MaterialSetAmbient
|
||||
Proto: void:Material material,Vector ambient_color
|
||||
Desc: Set material ambient color.
|
||||
#*/
|
||||
sq_register(vm, MaterialSetAmbient, "MaterialSetAmbient", _SC(".xx"));
|
||||
|
||||
/*#
|
||||
Func: MaterialGetGlossiness
|
||||
Proto: float:Material material
|
||||
Desc: Get material glossiness.
|
||||
#*/
|
||||
sq_register(vm, MaterialGetGlossiness, "MaterialGetGlossiness", _SC(".x"));
|
||||
/*#
|
||||
Func: MaterialSetGlossiness
|
||||
Proto: void:Material material,float glossiness
|
||||
Desc: Set material glossiness.
|
||||
#*/
|
||||
sq_register(vm, MaterialSetGlossiness, "MaterialSetGlossiness", _SC(".xn"));
|
||||
/*#
|
||||
Func: MaterialGetOpacity
|
||||
Proto: float:Material material
|
||||
Desc: Get material opacity.
|
||||
#*/
|
||||
sq_register(vm, MaterialGetOpacity, "MaterialGetOpacity", _SC(".x"));
|
||||
/*#
|
||||
Func: MaterialSetOpacity
|
||||
Proto: void:Material material,float opacity
|
||||
Desc: Set material opacity.
|
||||
See: MaterialSetBlendOperator
|
||||
#*/
|
||||
sq_register(vm, MaterialSetOpacity, "MaterialSetOpacity", _SC(".xn"));
|
||||
/*#
|
||||
Func: MaterialGetAlphaThreshold
|
||||
Proto: float:Material material
|
||||
Desc: Get material alpha threshold.
|
||||
#*/
|
||||
sq_register(vm, MaterialGetAlphaThreshold, "MaterialGetAlphaThreshold", _SC(".x"));
|
||||
/*#
|
||||
Func: MaterialSetAlphaThreshold
|
||||
Proto: void:Material material,float threshold
|
||||
Desc: Set material alpha threshold.
|
||||
#*/
|
||||
sq_register(vm, MaterialSetAlphaThreshold, "MaterialSetAlphaThreshold", _SC(".xn"));
|
||||
/*#
|
||||
Func: MaterialGetDepthBias
|
||||
Proto: float:Material material
|
||||
Desc: Get material depth bias.
|
||||
#*/
|
||||
sq_register(vm, MaterialGetDepthBias, "MaterialGetDepthBias", _SC(".x"));
|
||||
/*#
|
||||
Func: MaterialSetDepthBias
|
||||
Proto: void:Material material,float depth_bias
|
||||
Desc: Set material depth bias.
|
||||
#*/
|
||||
sq_register(vm, MaterialSetDepthBias, "MaterialSetDepthBias", _SC(".xn"));
|
||||
/*#
|
||||
Func: MaterialGetTexture
|
||||
Proto: Texture:Material material,int slot
|
||||
Desc: Get texture at a given material slot.
|
||||
#*/
|
||||
sq_register(vm, MaterialGetTexture, "MaterialGetTexture", _SC(".xn"));
|
||||
/*#
|
||||
Func: MaterialSetTexture
|
||||
Proto: void:Material material,int slot,Texture texture
|
||||
Desc: Set texture at a given material slot.
|
||||
#*/
|
||||
sq_register(vm, MaterialSetTexture, "MaterialSetTexture", _SC(".xnx"));
|
||||
/*#
|
||||
Func: MaterialGetShader
|
||||
Proto: MaterialShader:Material material
|
||||
Desc: Return the material shader for a given material.
|
||||
Note: A material shader encapsulates all the variants of a shader required to render a material.
|
||||
#*/
|
||||
sq_register(vm, MaterialGetShader, "MaterialGetShader", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: MaterialGeneric
|
||||
Desc: Generic functions
|
||||
#*/
|
||||
/*#
|
||||
Func: MaterialGetName
|
||||
Proto: string:Material mat
|
||||
Desc: Get material name.
|
||||
#*/
|
||||
sq_register(vm, MaterialGetName, "MaterialGetName", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Func: MaterialClone
|
||||
Proto: Material:Material mat
|
||||
Desc: Clone a material (create an independent copy in memory).
|
||||
Note: The cloned material has all the same textures, properties, and configuration as the original, but changes to the clone won't affect the original material.
|
||||
Example: local mat_clone = MaterialClone(original_material)
|
||||
#*/
|
||||
sq_register(vm, MaterialClone, "MaterialClone", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: MaterialFlag
|
||||
Desc: Rendering flag functions
|
||||
#*/
|
||||
/*#
|
||||
Func: MaterialSetRenderFlag
|
||||
Proto: void:Material mat,MaterialRenderFlag flag,bool state
|
||||
Desc: Add or remove a material render flag.
|
||||
Example:
|
||||
// Set the first material of a geometry to be double-sided.
|
||||
local mat = GeometryGetMaterialFromIndex(geo, 0)
|
||||
MaterialSetRenderFlag(mat, MaterialRenderDoubleSided, true)
|
||||
#*/
|
||||
sq_register(vm, MaterialFlagSet, "MaterialFlagSet", _SC(".xib"));
|
||||
sq_register(vm, MaterialFlagSet, "MaterialSetRenderFlag", _SC(".xib"));
|
||||
/*#
|
||||
Func: MaterialTestRenderFlag
|
||||
Proto: bool:Material mat,MaterialRenderFlag flag
|
||||
Desc: Test a material render flag.
|
||||
#*/
|
||||
sq_register(vm, MaterialFlagGet, "MaterialFlagGet", _SC(".xi"));
|
||||
sq_register(vm, MaterialFlagGet, "MaterialTestRenderFlag", _SC(".xi"));
|
||||
|
||||
/*#
|
||||
Func: MaterialSetBlendOperator
|
||||
Proto: void:Material mat,MaterialBlendOperator op
|
||||
Desc: Set the material blend operator. The blend operator controls how a material is composited onto screen.
|
||||
Example:
|
||||
// Set the first material of a geometry to use additive blending.
|
||||
local mat = GeometryGetMaterialFromIndex(geo, 0)
|
||||
MaterialSetBlendOperator(mat, MaterialBlendAdditive)
|
||||
#*/
|
||||
sq_register(vm, MaterialSetBlendOperator, "MaterialSetBlendOperator", _SC(".xi"));
|
||||
/*#
|
||||
Func: MaterialGetBlendOperator
|
||||
Proto: MaterialBlendOperator:Material mat
|
||||
Desc: Get the material blend operator.
|
||||
See: MaterialSetBlendOperator
|
||||
#*/
|
||||
sq_register(vm, MaterialGetBlendOperator, "MaterialGetBlendOperator", _SC(".x"));
|
||||
|
||||
//
|
||||
|
||||
sq_pushroottable(vm);
|
||||
sq_pushstring(vm, "NullMaterial", -1); CObject::Push(vm, NULL, typetag_Material); sq_newslot(vm, -3, true);
|
||||
|
||||
using GS::Core::Material;
|
||||
|
||||
/*#
|
||||
Enum: MaterialBlendOperator
|
||||
Values: MaterialBlendNone,MaterialBlendAlpha,MaterialBlendAdditive
|
||||
#*/
|
||||
sq_pushstring(vm, "MaterialBlendNone", -1); sq_pushinteger(vm, Material::Blend_None); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "MaterialBlendAlpha", -1); sq_pushinteger(vm, Material::Blend_Alpha); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "MaterialBlendAdditive", -1); sq_pushinteger(vm, Material::Blend_Add); sq_newslot(vm, -3, true);
|
||||
|
||||
/*#
|
||||
Enum: MaterialRenderFlag
|
||||
Values: MaterialRenderUnlit,MaterialRenderSmooth,MaterialRenderNormalMapTangent,MaterialRenderNoFog,MaterialRenderDoubleSided,MaterialRenderWire,MaterialRenderVertexColor,MaterialRenderParralax,MaterialRenderToonShading,MaterialRenderNoDepthWrite,MaterialRenderNoDepthTest,MaterialRenderAlphaSoftZ,MaterialRenderAlphaInShadow
|
||||
#*/
|
||||
sq_pushstring(vm, "MaterialRenderUnlit", -1); sq_pushinteger(vm, Material::Render_Unlit); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "MaterialRenderSmooth", -1); sq_pushinteger(vm, Material::Render_Smooth); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "MaterialRenderNormalMapTangent", -1); sq_pushinteger(vm, Material::Render_NormalTangent); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "MaterialRenderNoFog", -1); sq_pushinteger(vm, Material::Render_NoFog); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushstring(vm, "MaterialRenderDoubleSided", -1); sq_pushinteger(vm, Material::Render_DoubleSided); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "MaterialRenderWire", -1); sq_pushinteger(vm, Material::Render_Wire); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "MaterialRenderVertexColor", -1); sq_pushinteger(vm, Material::Render_VertexColor); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "MaterialRenderParralax", -1); sq_pushinteger(vm, Material::Render_ParralaxDisp); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "MaterialRenderToonShading", -1); sq_pushinteger(vm, Material::Render_Toon); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushstring(vm, "MaterialRenderNoDepthWrite", -1); sq_pushinteger(vm, Material::Render_NoZWrite); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "MaterialRenderNoDepthTest", -1); sq_pushinteger(vm, Material::Render_NoZTest); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushstring(vm, "MaterialRenderAlphaSoftZ", -1); sq_pushinteger(vm, Material::Render_AlphaSoftZ); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "MaterialRenderAlphaInShadow", -1); sq_pushinteger(vm, Material::Render_AlphaInShadow); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@ -0,0 +1,72 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "core/render_data.h"
|
||||
|
||||
using namespace GS::Render;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MaterialShaderSetUniformValue(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(shader, MaterialShader, typetag_MaterialShader)
|
||||
__SQ_GETSTRING(name)
|
||||
__SQ_GETVECTOR(value)
|
||||
bool r = shader->SetUserUniformValue(name, value);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(r)
|
||||
}
|
||||
SQInteger MaterialShaderSetUniformTexture(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(shader, MaterialShader, typetag_MaterialShader)
|
||||
__SQ_GETSTRING(name)
|
||||
__SQ_GETSAFEPTRALLOWNULL(t, Texture, typetag_Texture)
|
||||
bool r = shader->SetUserUniformValue(name, t);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(r)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterMaterialShaderBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Material Shader
|
||||
Type: MaterialShader
|
||||
Desc: A material shader holds all the variants of a shader required to render a material.
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: MaterialShaderGeneral
|
||||
Desc: General functions
|
||||
#*/
|
||||
/*#
|
||||
Func: MaterialShaderSetUniformValue
|
||||
Proto: bool:MaterialShader shader,String name,Vector value
|
||||
Desc: Set uniform value in a material shader.
|
||||
Note: The value is always passed as a vector of 4 floats, if the uniform type is smaller than vec4 unused entries of the vector are ignored.
|
||||
Example:
|
||||
local shader = MaterialGetShader(material)
|
||||
// u_user_param is a float.
|
||||
MaterialShaderSetUniformValue(shader, "u_user_param", Vector(1.0, 0.0, 0.0, 0.0))
|
||||
#*/
|
||||
sq_register(vm, MaterialShaderSetUniformValue, "MaterialShaderSetUniformValue", _SC(".xsx"));
|
||||
/*#
|
||||
Func: MaterialShaderSetUniformTexture
|
||||
Proto: bool:MaterialShader shader,String name,Texture texture
|
||||
Desc: Set uniform texture in a material shader.
|
||||
Example:
|
||||
local shader = MaterialGetShader(material)
|
||||
// u_user_tex is a Texture2D.
|
||||
MaterialShaderSetUniformTexture(shader, "u_user_tex", ResourceFactoryLoadTexture(g_factory, "textures/texture.png"))
|
||||
#*/
|
||||
sq_register(vm, MaterialShaderSetUniformTexture, "MaterialShaderSetUniformTexture", _SC(".xsx"));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
165
include/modules/script_squirrel/legacy/matrix_binding.cpp
Normal file
165
include/modules/script_squirrel/legacy/matrix_binding.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "script_squirrel/cobject/matrix_decl.h"
|
||||
#include "math/matrix4.h"
|
||||
#include "math/matrix3.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PushMatrix4(HSQUIRRELVM vm, const Matrix4 &mtx)
|
||||
{
|
||||
push_Matrix4(vm, mtx);
|
||||
/*
|
||||
if (!CreateClassInstance(vm, "Matrix4", true))
|
||||
return sq_suspendvm(vm);
|
||||
|
||||
SetTableKey("m00", sq_pushfloat, -1, mtx.m[0][0]);
|
||||
SetTableKey("m10", sq_pushfloat, -1, mtx.m[1][0]);
|
||||
SetTableKey("m20", sq_pushfloat, -1, mtx.m[2][0]);
|
||||
SetTableKey("m30", sq_pushfloat, -1, mtx.m[3][0]);
|
||||
SetTableKey("m01", sq_pushfloat, -1, mtx.m[0][1]);
|
||||
SetTableKey("m11", sq_pushfloat, -1, mtx.m[1][1]);
|
||||
SetTableKey("m21", sq_pushfloat, -1, mtx.m[2][1]);
|
||||
SetTableKey("m31", sq_pushfloat, -1, mtx.m[3][1]);
|
||||
SetTableKey("m02", sq_pushfloat, -1, mtx.m[0][2]);
|
||||
SetTableKey("m12", sq_pushfloat, -1, mtx.m[1][2]);
|
||||
SetTableKey("m22", sq_pushfloat, -1, mtx.m[2][2]);
|
||||
SetTableKey("m32", sq_pushfloat, -1, mtx.m[3][2]);
|
||||
SetTableKey("m03", sq_pushfloat, -1, mtx.m[0][3]);
|
||||
SetTableKey("m13", sq_pushfloat, -1, mtx.m[1][3]);
|
||||
SetTableKey("m23", sq_pushfloat, -1, mtx.m[2][3]);
|
||||
SetTableKey("m33", sq_pushfloat, -1, mtx.m[3][3]);
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
SQInteger GetMatrix4(HSQUIRRELVM vm, int idx, Matrix4 &mtx)
|
||||
{
|
||||
GetTableKey("m00", sq_getfloat, idx, mtx.m[0][0]);
|
||||
GetTableKey("m10", sq_getfloat, idx, mtx.m[1][0]);
|
||||
GetTableKey("m20", sq_getfloat, idx, mtx.m[2][0]);
|
||||
GetTableKey("m30", sq_getfloat, idx, mtx.m[3][0]);
|
||||
GetTableKey("m01", sq_getfloat, idx, mtx.m[0][1]);
|
||||
GetTableKey("m11", sq_getfloat, idx, mtx.m[1][1]);
|
||||
GetTableKey("m21", sq_getfloat, idx, mtx.m[2][1]);
|
||||
GetTableKey("m31", sq_getfloat, idx, mtx.m[3][1]);
|
||||
GetTableKey("m02", sq_getfloat, idx, mtx.m[0][2]);
|
||||
GetTableKey("m12", sq_getfloat, idx, mtx.m[1][2]);
|
||||
GetTableKey("m22", sq_getfloat, idx, mtx.m[2][2]);
|
||||
GetTableKey("m32", sq_getfloat, idx, mtx.m[3][2]);
|
||||
GetTableKey("m03", sq_getfloat, idx, mtx.m[0][3]);
|
||||
GetTableKey("m13", sq_getfloat, idx, mtx.m[1][3]);
|
||||
GetTableKey("m23", sq_getfloat, idx, mtx.m[2][3]);
|
||||
GetTableKey("m33", sq_getfloat, idx, mtx.m[3][3]);
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PushMatrix3(HSQUIRRELVM vm, const Matrix3 &mtx)
|
||||
{
|
||||
push_Matrix3(vm, mtx);
|
||||
/*
|
||||
if (!CreateClassInstance(vm, "Matrix3", true))
|
||||
return sq_suspendvm(vm);
|
||||
|
||||
SetTableKey("m00", sq_pushfloat, -1, mtx.m[0][0]);
|
||||
SetTableKey("m10", sq_pushfloat, -1, mtx.m[1][0]);
|
||||
SetTableKey("m20", sq_pushfloat, -1, mtx.m[2][0]);
|
||||
SetTableKey("m01", sq_pushfloat, -1, mtx.m[0][1]);
|
||||
SetTableKey("m11", sq_pushfloat, -1, mtx.m[1][1]);
|
||||
SetTableKey("m21", sq_pushfloat, -1, mtx.m[2][1]);
|
||||
SetTableKey("m02", sq_pushfloat, -1, mtx.m[0][2]);
|
||||
SetTableKey("m12", sq_pushfloat, -1, mtx.m[1][2]);
|
||||
SetTableKey("m22", sq_pushfloat, -1, mtx.m[2][2]);
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
SQInteger GetMatrix3(HSQUIRRELVM vm, int idx, Matrix3 &mtx)
|
||||
{
|
||||
GetTableKey("m00", sq_getfloat, idx, mtx.m[0][0]);
|
||||
GetTableKey("m10", sq_getfloat, idx, mtx.m[1][0]);
|
||||
GetTableKey("m20", sq_getfloat, idx, mtx.m[2][0]);
|
||||
GetTableKey("m01", sq_getfloat, idx, mtx.m[0][1]);
|
||||
GetTableKey("m11", sq_getfloat, idx, mtx.m[1][1]);
|
||||
GetTableKey("m21", sq_getfloat, idx, mtx.m[2][1]);
|
||||
GetTableKey("m02", sq_getfloat, idx, mtx.m[0][2]);
|
||||
GetTableKey("m12", sq_getfloat, idx, mtx.m[1][2]);
|
||||
GetTableKey("m22", sq_getfloat, idx, mtx.m[2][2]);
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger RotationMatrixFromDirection(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETVECTOR(direction))
|
||||
__SQ_RETURNMATRIX3(Matrix3::FromOrthonormalBasis(direction))
|
||||
}
|
||||
SQInteger RotationMatrixFromDirectionAndUp(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETVECTOR(direction)
|
||||
__SQ_GETVECTOR(up)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNMATRIX3(Matrix3::FromOrthonormalBasis(direction, &up))
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger EulerFromDirection(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETVECTOR(direction))
|
||||
__SQ_RETURNVECTOR(Matrix3::FromOrthonormalBasis(direction).AsEuler())
|
||||
}
|
||||
SQInteger EulerFromDirectionAndUp(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETVECTOR(direction)
|
||||
__SQ_GETVECTOR(up)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNVECTOR(Matrix3::FromOrthonormalBasis(direction, &up).AsEuler())
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MatrixToEuler(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETMATRIX3(matrix)
|
||||
__SQ_GETINT(rorder)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNVECTOR(matrix.AsEuler((Math::rOrder)rorder))
|
||||
}
|
||||
SQInteger TransformationMatrix(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(4)
|
||||
__SQ_GETVECTOR(p)
|
||||
__SQ_GETVECTOR(r)
|
||||
__SQ_GETVECTOR(s)
|
||||
__SQ_GETVECTOR(t)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNMATRIX4(Matrix4::TransformationMatrix(p, r, s, &t))
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterMatrixBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
using namespace GS::Script;
|
||||
|
||||
sq_register(vm, MatrixToEuler, "MatrixToEuler", _SC(".xi"));
|
||||
sq_register(vm, TransformationMatrix, "TransformationMatrix", _SC(".xxxx"));
|
||||
|
||||
sq_register(vm, RotationMatrixFromDirection, "RotationMatrixFromDirection", _SC(".x"));
|
||||
sq_register(vm, RotationMatrixFromDirectionAndUp, "RotationMatrixFromDirectionAndUp", _SC(".xx"));
|
||||
sq_register(vm, EulerFromDirection, "EulerFromDirection", _SC(".x"));
|
||||
sq_register(vm, EulerFromDirectionAndUp, "EulerFromDirectionAndUp", _SC(".xx"));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
399
include/modules/script_squirrel/legacy/mixer_binding.cpp
Normal file
399
include/modules/script_squirrel/legacy/mixer_binding.cpp
Normal file
@ -0,0 +1,399 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "core/sound.h"
|
||||
#include "core/mixer.h"
|
||||
|
||||
using namespace GS::Audio;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MixerSetGain(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETFLOAT(gain)
|
||||
__SQ_GETEND
|
||||
mixer->SetMasterVolume(gain);
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MixerMute(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
mixer->SetMasterVolume(0);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MixerUnmute(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
mixer->SetMasterVolume(1);
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MixerChannelLock(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_RETURNINT(mixer->LockChannel())
|
||||
}
|
||||
SQInteger MixerChannelUnlock(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETINT(channel)
|
||||
__SQ_GETEND
|
||||
mixer->UnlockChannel(channel);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MixerChannelUnlockAll(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
mixer->UnlockAllChannels();
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MixerChannelStart(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETINT(channel)
|
||||
__SQ_GETSAFEPTR(sound, Sound, typetag_Sound)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(mixer->Start(channel, sound->mixer_data))
|
||||
}
|
||||
SQInteger MixerChannelStartStream(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETINT(channel)
|
||||
__SQ_GETSTRING(uri)
|
||||
int r = mixer->Stream(channel, uri);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(r != -1)
|
||||
}
|
||||
SQInteger MixerSoundStartFast(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETSAFEPTR(sound, Sound, typetag_Sound)
|
||||
bool r = mixer->StartFast(-1, sound->mixer_data);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(r)
|
||||
}
|
||||
SQInteger MixerSoundStart(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETSAFEPTR(sound, Sound, typetag_Sound)
|
||||
int channel = mixer->Start(-1, sound->mixer_data);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNINT(channel)
|
||||
}
|
||||
SQInteger MixerStreamStartFast(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETSTRING(uri)
|
||||
bool r = mixer->StreamFast(-1, uri);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(r)
|
||||
}
|
||||
SQInteger MixerStreamStart(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETSTRING(uri)
|
||||
int channel = mixer->Stream(-1, uri);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNINT(channel)
|
||||
}
|
||||
SQInteger MixerChannelPause(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETINT(channel)
|
||||
__SQ_GETEND
|
||||
mixer->Pause(channel);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MixerChannelResume(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETINT(channel)
|
||||
__SQ_GETEND
|
||||
mixer->Resume(channel);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MixerChannelGetState(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETINT(channel)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNINT(0)
|
||||
}
|
||||
SQInteger MixerChannelStop(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETINT(channel)
|
||||
__SQ_GETEND
|
||||
mixer->Stop(channel);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MixerChannelStopAll(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
// mixer->StopAllChannels();
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MixerChannelSetGain(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETINT(channel)
|
||||
__SQ_GETFLOAT(gain)
|
||||
__SQ_GETEND
|
||||
mixer->SetChannelVolume(channel, gain);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MixerChannelSetPitch(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETINT(channel)
|
||||
__SQ_GETFLOAT(pitch)
|
||||
__SQ_GETEND
|
||||
mixer->SetChannelPitch(channel, pitch);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MixerChannelSetPanning(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETINT(channel)
|
||||
__SQ_GETFLOAT(panning)
|
||||
__SQ_GETEND
|
||||
mixer->SetChannelPanning(channel, panning);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MixerChannelSetLoopMode(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETINT(channel)
|
||||
__SQ_GETINT(loop)
|
||||
__SQ_GETEND
|
||||
mixer->SetChannelLoopMode(channel, (IMixer::Loop)loop);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger MixerChannelSetLoopPosition(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(mixer, IMixer, typetag_Mixer)
|
||||
__SQ_GETINT(channel)
|
||||
__SQ_GETINT(position)
|
||||
__SQ_GETEND
|
||||
mixer->SetChannelLoopPosition(channel, position);
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterMixerBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Mixer
|
||||
Type: Mixer
|
||||
Type: Channel
|
||||
Related: Sound,ResourceFactory
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: ChannelManagement
|
||||
Desc: Channel management functions
|
||||
#*/
|
||||
/*#
|
||||
Func: MixerChannelGetState
|
||||
Proto: ChannelState:Mixer,int channel
|
||||
Desc: Return the channel state.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelGetState, "MixerChannelGetState", _SC(".xi"));
|
||||
/*#
|
||||
Func: MixerChannelStop
|
||||
Proto: void:Mixer,int channel
|
||||
Desc: Stop playback on a given channel.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelStop, "MixerChannelStop", _SC(".xi"));
|
||||
/*#
|
||||
Func: MixerChannelPause
|
||||
Proto: void:Mixer,int channel
|
||||
Desc: Pause playback on a given channel.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelPause, "MixerChannelPause", _SC(".xi"));
|
||||
/*#
|
||||
Func: MixerChannelResume
|
||||
Proto: void:Mixer,int channel
|
||||
Desc: Resume playback on a given channel.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelResume, "MixerChannelResume", _SC(".xi"));
|
||||
/*#
|
||||
Func: MixerChannelStopAll
|
||||
Proto: void:Mixer
|
||||
Desc: Stop replay on all mixer channels.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelStopAll, "MixerChannelStopAll", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: MixerControl
|
||||
Desc: Mixer control functions
|
||||
#*/
|
||||
/*#
|
||||
Func: MixerSetGain
|
||||
Proto: void:Mixer mixer,float gain
|
||||
Desc: Set the global mixer gain.
|
||||
#*/
|
||||
sq_register(vm, MixerSetGain, "MixerSetGain", _SC(".xn"));
|
||||
/*#
|
||||
Func: MixerPlaySoundFast
|
||||
Proto: bool:Mixer mixer,Sound sound
|
||||
Desc: Play a sound on the first channel available, this function returns immediately and the channel used for replay is not returned.
|
||||
See: ResourceFactoryLoadSound
|
||||
#*/
|
||||
sq_register(vm, MixerSoundStartFast, "MixerSoundStartFast", _SC(".xx"));
|
||||
sq_register(vm, MixerSoundStartFast, "MixerPlaySoundFast", _SC(".xx"));
|
||||
/*#
|
||||
Func: MixerPlaySound
|
||||
Proto: Channel:Mixer mixer,Sound sound
|
||||
Desc: Play a sound on the first channel available, the channel used for replay is returned. If no free channel was found -1 is returned.
|
||||
Note: Use MixerPlaySoundFast to prevent waiting for the mixer thread to return the channel used for playback if you do not need this information.
|
||||
See: MixerPlaySoundFast,ResourceFactoryLoadSound,MixerChannelPlaySound
|
||||
#*/
|
||||
sq_register(vm, MixerSoundStart, "MixerSoundStart", _SC(".xx"));
|
||||
sq_register(vm, MixerSoundStart, "MixerPlaySound", _SC(".xx"));
|
||||
/*#
|
||||
Func: MixerStartStreamFast
|
||||
Proto: bool:Mixer,uri
|
||||
Desc: Play a stream on the first channel available, this function returns immediately and the channel used for replay is not returned.
|
||||
#*/
|
||||
sq_register(vm, MixerStreamStartFast, "MixerStreamStartFast", _SC(".xs"));
|
||||
sq_register(vm, MixerStreamStartFast, "MixerStartStreamFast", _SC(".xs"));
|
||||
/*#
|
||||
Func: MixerStartStream
|
||||
Proto: Channel:Mixer,uri
|
||||
Desc: Play a stream on the first channel available, the channel used for replay is returned. If no free channel was found -1 is returned.
|
||||
Note: Use MixerStartStreamFast to prevent waiting for the mixer thread to return the channel used for playback if you do not need this information.
|
||||
See: MixerStartStreamFast,MixerChannelStartStream
|
||||
#*/
|
||||
sq_register(vm, MixerStreamStart, "MixerStreamStart", _SC(".xs"));
|
||||
sq_register(vm, MixerStreamStart, "MixerStartStream", _SC(".xs"));
|
||||
/*#
|
||||
Func: MixerMute
|
||||
Proto: void:Mixer
|
||||
Desc: Mute all sound output.
|
||||
#*/
|
||||
sq_register(vm, MixerMute, "MixerMute", _SC(".x"));
|
||||
/*#
|
||||
Func: MixerUnmute
|
||||
Proto: void:Mixer
|
||||
Desc: Unmute all sound output.
|
||||
#*/
|
||||
sq_register(vm, MixerUnmute, "MixerUnmute", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: ChannelControl
|
||||
Desc: Channel control functions
|
||||
#*/
|
||||
/*#
|
||||
Func: MixerChannelLock
|
||||
Proto: Channel:Mixer
|
||||
Desc: Lock a new mixer channel.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelLock, "MixerChannelLock", _SC(".x"));
|
||||
/*#
|
||||
Func: MixerChannelUnlock
|
||||
Proto: void:Mixer,Channel
|
||||
Desc: Unlock channel.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelUnlock, "MixerChannelUnlock", _SC(".xi"));
|
||||
/*#
|
||||
Func: MixerChannelUnlockAll
|
||||
Proto: void:Mixer
|
||||
Desc: Unlock all channels.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelUnlockAll, "MixerChannelUnlockAll", _SC(".x"));
|
||||
/*#
|
||||
Func: MixerChannelPlaySound
|
||||
Proto: bool:Mixer,Channel,Sound
|
||||
Desc: Play a sound on a specific channel. Returns true on success, false otherwise.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelStart, "MixerChannelStart", _SC(".xix"));
|
||||
sq_register(vm, MixerChannelStart, "MixerChannelPlaySound", _SC(".xix"));
|
||||
/*#
|
||||
Func: MixerChannelStartStream
|
||||
Proto: bool:Mixer,Channel,string uri
|
||||
Desc: Play a stream on a specific channel. Returns true on success, false otherwise.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelStartStream, "MixerChannelStartStream", _SC(".xis"));
|
||||
|
||||
/*#
|
||||
Func: MixerChannelSetGain
|
||||
Proto: void:Mixer,Channel,float gain
|
||||
Desc: Set channel gain. Note: The channel gain is not reset by starting new sounds.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelSetGain, "MixerChannelSetGain", _SC(".xin"));
|
||||
/*#
|
||||
Func: MixerChannelSetPitch
|
||||
Proto: void:Mixer,Channel,float pitch
|
||||
Desc: Set channel pitch (Default: 1.0). Note: The channel pitch is not reset by starting new sounds.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelSetPitch, "MixerChannelSetPitch", _SC(".xin"));
|
||||
/*#
|
||||
Func: MixerChannelSetPanning
|
||||
Proto: void:Mixer,Channel,float panning
|
||||
Desc: Set channel panning (Default: 0.5). Note: The channel panning is not reset by starting new sounds.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelSetPanning, "MixerChannelSetPanning", _SC(".xin"));
|
||||
/*#
|
||||
Func: MixerChannelSetLoopMode
|
||||
Proto: void:Mixer,Channel,ChannelLoop loop
|
||||
Desc: Set channel loop mode.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelSetLoopMode, "MixerChannelSetLoopMode", _SC(".xii"));
|
||||
/*#
|
||||
Func: MixerChannelSetLoopPosition
|
||||
Proto: void:Mixer,Channel,int ms
|
||||
Desc: Set channel loop position in millisecond, the loop mode must be set to LoopRepeat for this setting to have any effect.
|
||||
#*/
|
||||
sq_register(vm, MixerChannelSetLoopPosition, "MixerChannelSetLoopPosition", _SC(".xii"));
|
||||
|
||||
// Push defines.
|
||||
sq_pushroottable(vm);
|
||||
|
||||
/*#
|
||||
Enum: ChannelLoop
|
||||
Values: LoopNone,LoopRepeat
|
||||
#*/
|
||||
sq_pushstring(vm, "LoopNone", -1); sq_pushinteger(vm, IMixer::None); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "LoopRepeat", -1); sq_pushinteger(vm, IMixer::Repeat); sq_newslot(vm, -3, true);
|
||||
|
||||
/*#
|
||||
Enum: ChannelState
|
||||
Values: ChannelStateInvalid,ChannelStateStopped,ChannelStatePlaying,ChannelStatePaused
|
||||
#*/
|
||||
sq_pushstring(vm, "ChannelStateInvalid", -1); sq_pushinteger(vm, IMixer::Invalid); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelStateStopped", -1); sq_pushinteger(vm, IMixer::Stopped); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelStatePlaying", -1); sq_pushinteger(vm, IMixer::Playing); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelStatePaused", -1); sq_pushinteger(vm, IMixer::Paused); sq_newslot(vm, -3, true);
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
250
include/modules/script_squirrel/legacy/motion_binding.cpp
Normal file
250
include/modules/script_squirrel/legacy/motion_binding.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "motion/motion.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::Script;
|
||||
|
||||
/*
|
||||
#include "micropather.h"
|
||||
using namespace micropather;
|
||||
|
||||
#include "pathfinding.h"
|
||||
|
||||
MicroPather *pather;
|
||||
MapPathFinder* pathfinding_map;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger NodePathFinder_CreateNode(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETINT(id)
|
||||
__SQ_GETINT(id_child)
|
||||
__SQ_GETEND
|
||||
|
||||
pathfinding_map->AddChildToNode(id, id_child);
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger NodePathFinder_AddChild(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETINT(id)
|
||||
__SQ_GETFLOAT(weight)
|
||||
__SQ_GETEND
|
||||
|
||||
pathfinding_map->CreateNode(weight, id);
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger CreateMicroPather(HSQUIRRELVM vm)
|
||||
{
|
||||
pathfinding_map = new MapPathFinder();
|
||||
pather = new MicroPather(pathfinding_map, 20);
|
||||
__SQ_RETURN
|
||||
}
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MotionGetClosestPoint(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(motion, Motion, typetag_Motion)
|
||||
__SQ_GETVECTOR(p)
|
||||
__SQ_GETEND
|
||||
|
||||
Vector4 closest;
|
||||
if (motion)
|
||||
motion->GetClosestPoint(p, closest);
|
||||
__SQ_RETURNVECTOR(closest)
|
||||
}
|
||||
SQInteger MotionGetClosestTime(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(motion, Motion, typetag_Motion)
|
||||
__SQ_GETVECTOR(p)
|
||||
__SQ_GETEND
|
||||
|
||||
Vector4 closest;
|
||||
float closest_t = 0.f;
|
||||
if (motion)
|
||||
motion->GetClosestPoint(p, closest, &closest_t);
|
||||
__SQ_RETURNFLOAT(closest_t);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MotionEvaluateData(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(motion, Motion, typetag_Motion)
|
||||
__SQ_GETFLOAT(t)
|
||||
__SQ_GETEND
|
||||
GS::Variant sample;
|
||||
if (motion)
|
||||
motion->EvaluateData(Time::fromSec(t), sample);
|
||||
__SQ_RETURNSTRING(sample.s_value)
|
||||
}
|
||||
SQInteger MotionEvaluatePosition(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(motion, Motion, typetag_Motion)
|
||||
__SQ_GETFLOAT(t)
|
||||
__SQ_GETEND
|
||||
Vector4 sample(0, 0, 0);
|
||||
if (motion)
|
||||
motion->EvaluatePosition(Time::fromSec(t), sample, Curve::Repeat);
|
||||
__SQ_RETURNVECTOR(sample)
|
||||
}
|
||||
|
||||
SQInteger MotionEvaluateDirection(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(motion, Motion, typetag_Motion)
|
||||
__SQ_GETFLOAT(t)
|
||||
__SQ_GETEND
|
||||
Vector4 sample(0, 0, 0);
|
||||
if (motion)
|
||||
motion->EvaluateDirection(Time::fromSec(t), sample, Curve::Repeat);
|
||||
__SQ_RETURNVECTOR(sample)
|
||||
}
|
||||
|
||||
|
||||
SQInteger MotionEvaluatePositionConstant(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(motion, Motion, typetag_Motion)
|
||||
__SQ_GETFLOAT(t)
|
||||
__SQ_GETEND
|
||||
Vector4 sample(0, 0, 0);
|
||||
if (motion)
|
||||
motion->EvaluatePosition(Time::fromSec(t), sample, Curve::Constant);
|
||||
__SQ_RETURNVECTOR(sample)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger MotionGetName(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(m, Motion, typetag_Motion)
|
||||
__SQ_RETURNSTRING(m->name)
|
||||
}
|
||||
SQInteger MotionGetLength(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(m, Motion, typetag_Motion)
|
||||
__SQ_RETURNFLOAT(m->GetDuration().toSec())
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterMotionBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Motion
|
||||
Type: Motion
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: Motion
|
||||
Desc: Motion functions
|
||||
#*/
|
||||
/*#
|
||||
Func: MotionGetClosestPoint
|
||||
Proto: float:Motion,Vector
|
||||
Desc: Return the nearest point on this motion for the position given
|
||||
#*/
|
||||
sq_register(vm, MotionGetClosestPoint, "MotionGetClosestPoint", _SC(".xx"));
|
||||
/*#
|
||||
Func: MotionGetClosestTime
|
||||
Proto: float:Motion,Vector
|
||||
Desc: Return the time for the nearest position.
|
||||
#*/
|
||||
sq_register(vm, MotionGetClosestTime, "MotionGetClosestTime", _SC(".xx"));
|
||||
/*#
|
||||
Func: MotionGetName
|
||||
Proto: String:Motion
|
||||
Desc: Return motion name.
|
||||
#*/
|
||||
sq_register(vm, MotionGetName, "MotionGetName", _SC(".x"));
|
||||
/*#
|
||||
Func: MotionEvaluateData
|
||||
Proto: String:Motion,float time
|
||||
Desc: Evaluate the data in motion at the specified time.
|
||||
#*/
|
||||
sq_register(vm, MotionEvaluateData, "MotionEvaluateData", _SC(".xn"));
|
||||
/*#
|
||||
Func: MotionEvaluatePosition
|
||||
Proto: Vector:Motion,float time
|
||||
Desc: Evaluate position triplet (x, y, z) in motion at the specified time. Note that a motion may not have all or any of the channels required for this evaluation.
|
||||
#*/
|
||||
sq_register(vm, MotionEvaluatePosition, "MotionEvaluatePosition", _SC(".xn"));
|
||||
sq_register(vm, MotionEvaluateDirection, "MotionEvaluateDirection", _SC(".xn"));
|
||||
/*#
|
||||
Func: MotionEvaluatePositionConstant
|
||||
Proto: Vector:Motion,float time
|
||||
Desc: IT'S CLAMPED TO THE BEGINING AND END. Evaluate position triplet (x, y, z) in motion at the specified time. Note that a motion may not have all or any of the channels required for this evaluation.
|
||||
#*/
|
||||
sq_register(vm, MotionEvaluatePositionConstant, "MotionEvaluatePositionConstant", _SC(".xn"));
|
||||
|
||||
/*#
|
||||
Func: MotionGetLength
|
||||
Proto: float:Motion
|
||||
Desc: Return highest timecode in motion.
|
||||
#*/
|
||||
sq_register(vm, MotionGetLength, "MotionGetLength", _SC(".x"));
|
||||
|
||||
// Push defines.
|
||||
sq_pushroottable(vm);
|
||||
|
||||
sq_pushstring(vm, "ChannelNone", -1); sq_pushinteger(vm, MotionChannel::NoType); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushstring(vm, "ChannelXPos", -1); sq_pushinteger(vm, MotionChannel::XPos); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelYPos", -1); sq_pushinteger(vm, MotionChannel::YPos); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelZPos", -1); sq_pushinteger(vm, MotionChannel::ZPos); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelXRot", -1); sq_pushinteger(vm, MotionChannel::XRot); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelYRot", -1); sq_pushinteger(vm, MotionChannel::YRot); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelZRot", -1); sq_pushinteger(vm, MotionChannel::ZRot); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelXScl", -1); sq_pushinteger(vm, MotionChannel::XScl); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelYScl", -1); sq_pushinteger(vm, MotionChannel::YScl); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelZScl", -1); sq_pushinteger(vm, MotionChannel::ZScl); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushstring(vm, "ChannelXPiv", -1); sq_pushinteger(vm, MotionChannel::XPiv); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelYPiv", -1); sq_pushinteger(vm, MotionChannel::YPiv); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelZPiv", -1); sq_pushinteger(vm, MotionChannel::ZPiv); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushstring(vm, "ChannelRDif", -1); sq_pushinteger(vm, MotionChannel::RDif); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelGDif", -1); sq_pushinteger(vm, MotionChannel::GDif); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelBDif", -1); sq_pushinteger(vm, MotionChannel::BDif); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelRSpc", -1); sq_pushinteger(vm, MotionChannel::RSpc); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelGSpc", -1); sq_pushinteger(vm, MotionChannel::GSpc); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelBSpc", -1); sq_pushinteger(vm, MotionChannel::BSpc); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushstring(vm, "ChannelDiffuseIntensity", -1); sq_pushinteger(vm, MotionChannel::DiffuseIntensity); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelSpecularIntensity", -1); sq_pushinteger(vm, MotionChannel::SpecularIntensity); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushstring(vm, "ChannelConeAngle", -1); sq_pushinteger(vm, MotionChannel::ConeAngle); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelEdgeAngle", -1); sq_pushinteger(vm, MotionChannel::EdgeAngle); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushstring(vm, "ChannelAlpha", -1); sq_pushinteger(vm, MotionChannel::Alpha); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushstring(vm, "ChannelZoomFactor", -1); sq_pushinteger(vm, MotionChannel::ZoomFactor); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushstring(vm, "ChannelRange", -1); sq_pushinteger(vm, MotionChannel::Range); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushstring(vm, "ChannelFogStart", -1); sq_pushinteger(vm, MotionChannel::FogStart); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelFogEnd", -1); sq_pushinteger(vm, MotionChannel::FogEnd); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelRFog", -1); sq_pushinteger(vm, MotionChannel::RFog); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelGFog", -1); sq_pushinteger(vm, MotionChannel::GFog); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ChannelBFog", -1); sq_pushinteger(vm, MotionChannel::BFog); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
502
include/modules/script_squirrel/legacy/nml_binding.cpp
Normal file
502
include/modules/script_squirrel/legacy/nml_binding.cpp
Normal file
@ -0,0 +1,502 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "metafile/nml.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::NML;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
SQInteger MetafileGetRoots(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(metafile, File, typetag_Metafile)
|
||||
|
||||
sq_newarray(vm, 0);
|
||||
if (metafile)
|
||||
{
|
||||
NMLFileForeach(tag, *metafile)
|
||||
{
|
||||
CObject::Push(vm, tag, typetag_Metatag, false);
|
||||
sq_arrayappend(vm, -2);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
SQInteger MetatagGetChildren(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(metatag, Tag, typetag_Metatag)
|
||||
|
||||
sq_newarray(vm, 0);
|
||||
if (metatag)
|
||||
{
|
||||
NMLTagForeach(tag, *metatag)
|
||||
{
|
||||
CObject::Push(vm, tag, typetag_Metatag, false);
|
||||
sq_arrayappend(vm, -2);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
SQInteger MetafileNew(HSQUIRRELVM vm)
|
||||
{ __SQ_RETURNMANAGEDSAFEPTR(new File, typetag_Metafile) }
|
||||
SQInteger MetafileDelete(HSQUIRRELVM vm)
|
||||
{ __SQ_RETURN }
|
||||
|
||||
SQInteger MetafileLoadFromString(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mf, File, typetag_Metafile)
|
||||
__SQ_GETSTRING(file)
|
||||
bool success = Parser::LoadFromMemory((char *)file, String::strlen(file), *mf);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(success)
|
||||
}
|
||||
SQInteger MetafileLoad(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mf, File, typetag_Metafile)
|
||||
__SQ_GETSTRING(uri)
|
||||
bool success = Parser::Load(uri, *mf); // take care of the string
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(success)
|
||||
}
|
||||
SQInteger MetafileSave(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mf, File, typetag_Metafile)
|
||||
__SQ_GETSTRING(uri)
|
||||
bool success = Parser::Save(uri, *mf);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(success)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static Tag *CreateMetatagFromSquirrelStackEntry(HSQUIRRELVM vm, int idx, const char *path)
|
||||
{
|
||||
Tag *tag = NULL;
|
||||
switch (sq_gettype(vm, idx))
|
||||
{
|
||||
case OT_NULL:
|
||||
tag = new Tag(path);
|
||||
break;
|
||||
|
||||
case OT_INTEGER:
|
||||
{
|
||||
SQInteger value;
|
||||
sq_getinteger(vm, idx, &value);
|
||||
tag = new Tag(path, (int)value);
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_FLOAT:
|
||||
{
|
||||
float value;
|
||||
sq_getfloat(vm, idx, &value);
|
||||
tag = new Tag(path, value);
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_BOOL:
|
||||
{
|
||||
SQBool value;
|
||||
sq_getbool(vm, idx, &value);
|
||||
tag = new Tag(path, value ? true : false);
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_STRING:
|
||||
{
|
||||
const char *value;
|
||||
sq_getstring(vm, idx, &value);
|
||||
tag = new Tag(path, value);
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_TABLE:
|
||||
case OT_ARRAY:
|
||||
default:
|
||||
__LOG_E__ << "Cannot convert input Squirrel type to metatag value.\n";
|
||||
break;
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
SQInteger MetafileAddRoot(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mf, File, typetag_Metafile)
|
||||
__SQ_GETSTRING(path)
|
||||
Tag *tag = new Tag(path);
|
||||
if (!tag)
|
||||
return sq_throwerror(vm, "Failed to allocate metatag.");
|
||||
mf->AddRoot(tag);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(tag, typetag_Metatag)
|
||||
}
|
||||
SQInteger MetatagAddChild(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(itg, Tag, typetag_Metatag)
|
||||
__SQ_GETSTRING(path)
|
||||
Tag *tag = new Tag(path);
|
||||
if (!tag)
|
||||
return sq_throwerror(vm, "Failed to allocate metatag.");
|
||||
itg->AddChild(tag);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(tag, typetag_Metatag)
|
||||
}
|
||||
SQInteger MetatagDeleteChild(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(tag, Tag, typetag_Metatag)
|
||||
__SQ_GETSAFEPTR(child, Tag, typetag_Metatag)
|
||||
__SQ_GETEND
|
||||
|
||||
if (!tag->RemoveTag(child))
|
||||
return sq_throwerror(vm, "Child tag does not belong to this tag.");
|
||||
|
||||
__SQ_INVALIDATENATIVEREF(child);
|
||||
_safe_delete(child); // tags are not managed
|
||||
__SQ_RETURN
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
SQInteger MetafileAddRootWithValue(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(mf, File, typetag_Metafile)
|
||||
__SQ_GETSTRING(path)
|
||||
Tag *tag = CreateMetatagFromSquirrelStackEntry(vm, __SQ_STACKPOS, path);
|
||||
__SQ_GETUPDATESTACK
|
||||
__SQ_GETEND
|
||||
if (!tag)
|
||||
return sq_throwerror(vm, "Failed to add root tag to metafile.");
|
||||
mf->AddRoot(tag);
|
||||
__SQ_RETURNSAFEPTR(tag, typetag_Metatag)
|
||||
}
|
||||
SQInteger MetatagAddChildWithValue(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(itg, Tag, typetag_Metatag)
|
||||
__SQ_GETSTRING(path)
|
||||
Tag *tag = CreateMetatagFromSquirrelStackEntry(vm, __SQ_STACKPOS, path);
|
||||
__SQ_GETUPDATESTACK
|
||||
__SQ_GETEND
|
||||
if (!tag)
|
||||
return sq_throwerror(vm, "Failed to add child tag.");
|
||||
itg->AddChild(tag);
|
||||
__SQ_RETURNSAFEPTR(tag, typetag_Metatag)
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
SQInteger MetafileGetTag(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mf, File, typetag_Metafile)
|
||||
__SQ_GETSTRING(path)
|
||||
Tag *tag = mf->GetTag(path);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(tag, typetag_Metatag)
|
||||
}
|
||||
SQInteger MetafileGetTypedTag(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(mf, File, typetag_Metafile)
|
||||
__SQ_GETSTRING(path)
|
||||
__SQ_GETINT(type)
|
||||
Tag *tag = mf->GetTypedTag(path, (GS::Variant::Type)type);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(tag, typetag_Metatag)
|
||||
}
|
||||
SQInteger MetatagGetTag(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mf, Tag, typetag_Metatag)
|
||||
__SQ_GETSTRING(path)
|
||||
Tag *tag = mf->GetTag(path);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(tag, typetag_Metatag)
|
||||
}
|
||||
SQInteger MetatagGetTypedTag(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(mf, Tag, typetag_Metatag)
|
||||
__SQ_GETSTRING(path)
|
||||
__SQ_GETINT(type)
|
||||
Tag *tag = mf->GetTypedTag(path, (GS::Variant::Type)type);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(tag, typetag_Metatag)
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
SQInteger MetatagGetType(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(tag, Tag, typetag_Metatag)
|
||||
__SQ_RETURNINT((int)tag->GetValue().GetType())
|
||||
}
|
||||
SQInteger MetatagGetName(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(tag, Tag, typetag_Metatag)
|
||||
__SQ_RETURNSTRING(tag->name.c_str())
|
||||
}
|
||||
SQInteger MetatagSetName(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(tag, Tag, typetag_Metatag)
|
||||
__SQ_GETSTRING(_name)
|
||||
tag->name = _name;
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
SQInteger MetatagGetValue(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(tag, Tag, typetag_Metatag)
|
||||
|
||||
switch (tag->GetValue().GetType())
|
||||
{
|
||||
default:
|
||||
case GS::Variant::VariantNone:
|
||||
case GS::Variant::VariantBinary:
|
||||
break;
|
||||
|
||||
case GS::Variant::VariantBool:
|
||||
__SQ_RETURNBOOL(tag->GetBool())
|
||||
case GS::Variant::VariantInteger:
|
||||
__SQ_RETURNINT(tag->GetInteger())
|
||||
case GS::Variant::VariantFloat:
|
||||
__SQ_RETURNFLOAT(tag->GetReal())
|
||||
case GS::Variant::VariantString:
|
||||
__SQ_RETURNSTRING(tag->GetString())
|
||||
}
|
||||
|
||||
__LOG_E__ << "Cannot get value from tag '" << tag->name << "'. Unsupported type.\n";
|
||||
__SQ_RETURNINT(-1)
|
||||
}
|
||||
SQInteger MetatagSetValue(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(tag, Tag, typetag_Metatag)
|
||||
|
||||
switch (sq_gettype(vm, -1))
|
||||
{
|
||||
case OT_INTEGER:
|
||||
{
|
||||
__SQ_GETINT(value)
|
||||
tag->SetInteger(value);
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_FLOAT:
|
||||
{
|
||||
__SQ_GETFLOAT(value)
|
||||
tag->SetReal(value);
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_BOOL:
|
||||
{
|
||||
__SQ_GETBOOL(value)
|
||||
tag->SetBool(value ? true : false);
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_STRING:
|
||||
{
|
||||
__SQ_GETSTRING(value)
|
||||
tag->SetString(value);
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_NULL:
|
||||
case OT_TABLE:
|
||||
case OT_ARRAY:
|
||||
default:
|
||||
return sq_throwerror(vm, "Type cannot be converted to metatag value.");
|
||||
}
|
||||
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RegisterNMLBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Metafile
|
||||
Type: Metafile
|
||||
Type: Metatag
|
||||
Desc: A metafile is very similar to an XML file, it is mostly used to store data in a structured way.
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: MetaFile
|
||||
Desc: File functions
|
||||
#*/
|
||||
/*#
|
||||
Func: MetafileNew
|
||||
Proto: Metafile:
|
||||
Desc: Create a new metafile, this object is managed, the VM will free it.
|
||||
#*/
|
||||
sq_register(vm, MetafileNew, "MetafileNew", _SC("."));
|
||||
// Obsolete
|
||||
sq_register(vm, MetafileDelete, "MetafileDelete", _SC(".x"));
|
||||
/*#
|
||||
Func: MetafileLoadFromString
|
||||
Proto: bool:Metafile,string content
|
||||
Desc: Load metafile from a string.
|
||||
#*/
|
||||
sq_register(vm, MetafileLoadFromString, "MetafileLoadFromString", _SC(".xs"));
|
||||
/*#
|
||||
Func: MetafileLoad
|
||||
Proto: bool:Metafile,string path
|
||||
Desc: Load metafile from file system.
|
||||
#*/
|
||||
sq_register(vm, MetafileLoad, "MetafileLoad", _SC(".xs"));
|
||||
/*#
|
||||
Func: MetafileSave
|
||||
Proto: bool:Metafile,string path
|
||||
Desc: Save metafile to file system.
|
||||
#*/
|
||||
sq_register(vm, MetafileSave, "MetafileSave", _SC(".xs"));
|
||||
/*#
|
||||
Func: MetafileAddRoot
|
||||
Proto: Metatag:Metafile,string tag_name
|
||||
Desc: Add metafile root, returns the newly created metatag.
|
||||
#*/
|
||||
sq_register(vm, MetafileAddRoot, "MetafileAddRoot", _SC(".xs"));
|
||||
/*#
|
||||
Func: MetafileAddRootWithValue
|
||||
Proto: Metatag:Metafile,string tag_name,...
|
||||
Desc: Add metafile root, returns the newly created metatag.
|
||||
#*/
|
||||
sq_register(vm, MetafileAddRootWithValue, "MetafileAddRootWithValue", _SC(".xs."));
|
||||
/*#
|
||||
Func: MetafileGetRoots
|
||||
Proto: array:Metafile
|
||||
Desc: Return all root tags of a metafile in an array.
|
||||
#*/
|
||||
sq_register(vm, MetafileGetRoots, "MetafileGetRoots", _SC(".x"));
|
||||
/*#
|
||||
Func: MetafileGetTag
|
||||
Proto: Metatag:Metafile,string tag_path
|
||||
Desc: Get metatag from metafile, the metatag path is formatted as follow: tag:child:tag_id; (eg: 'Pref:Sound:Volume;').
|
||||
#*/
|
||||
sq_register(vm, MetafileGetTag, "MetafileGetTag", _SC(".xs"));
|
||||
/*#
|
||||
Func: MetafileGetTypedTag
|
||||
Proto: Metatag:Metafile,string tag_path,TagType
|
||||
Desc: Get metatag of a specific value type from a metafile.
|
||||
#*/
|
||||
sq_register(vm, MetafileGetTypedTag, "MetafileGetTypedTag", _SC(".xsi"));
|
||||
|
||||
/*#
|
||||
Section: MetaTag
|
||||
Desc: Tag functions
|
||||
#*/
|
||||
/*#
|
||||
Func: MetatagGetName
|
||||
Proto: string:Metatag
|
||||
Desc: Get metatag name.
|
||||
#*/
|
||||
sq_register(vm, MetatagGetName, "MetatagGetName", _SC(".x"));
|
||||
/*#
|
||||
Func: MetatagSetName
|
||||
Proto: void:Metatag,String
|
||||
Desc: Set metatag name.
|
||||
#*/
|
||||
sq_register(vm, MetatagSetName, "MetatagSetName", _SC(".xs"));
|
||||
/*#
|
||||
Func: MetatagGetType
|
||||
Proto: TagType:Metatag
|
||||
Desc: Get metatag type.
|
||||
#*/
|
||||
sq_register(vm, MetatagGetType, "MetatagGetType", _SC(".x"));
|
||||
/*#
|
||||
Func: MetatagGetValue
|
||||
Proto: ...:Metatag
|
||||
Desc: Get metatag value.
|
||||
#*/
|
||||
sq_register(vm, MetatagGetValue, "MetatagGetValue", _SC(".x"));
|
||||
/*#
|
||||
Func: MetatagSetValue
|
||||
Proto: void:Metatag,...
|
||||
Desc: Set metatag value, the value type is automatically handled.
|
||||
#*/
|
||||
sq_register(vm, MetatagSetValue, "MetatagSetValue", _SC(".x."));
|
||||
|
||||
/*#
|
||||
Func: MetatagDeleteChild
|
||||
Proto: void:Metatag tag, Metatag child
|
||||
Desc: Delete a metatag child tag.
|
||||
Note: The removed child tag is freed and all existing script references to it are invalidated.
|
||||
#*/
|
||||
sq_register(vm, MetatagDeleteChild, "MetatagDeleteChild", _SC(".xx"));
|
||||
/*#
|
||||
Func: MetatagAddChild
|
||||
Proto: Metatag:Metatag,string tag_name
|
||||
Desc: Add metatag child, returns the newly created metatag.
|
||||
#*/
|
||||
sq_register(vm, MetatagAddChild, "MetatagAddChild", _SC(".xs"));
|
||||
/*#
|
||||
Func: MetatagAddChildWithValue
|
||||
Proto: Metatag:Metatag,string tag_name,...
|
||||
Desc: Add metatag child, returns the newly created metatag.
|
||||
#*/
|
||||
sq_register(vm, MetatagAddChildWithValue, "MetatagAddChildWithValue", _SC(".xs."));
|
||||
|
||||
/*#
|
||||
Func: MetatagGetTag
|
||||
Proto: Metatag:Metatag,string tag_path
|
||||
Desc: Find metatag child.
|
||||
#*/
|
||||
sq_register(vm, MetatagGetTag, "MetatagGetTag", _SC(".xs"));
|
||||
/*#
|
||||
Func: MetatagGetTypedTag
|
||||
Proto: Metatag:Metatag,string tag_path,TagType
|
||||
Desc: Find child of a specific value type from a metatag.
|
||||
#*/
|
||||
sq_register(vm, MetatagGetTypedTag, "MetatagGetTypedTag", _SC(".xsi"));
|
||||
/*#
|
||||
Func: MetatagGetChildren
|
||||
Proto: Array:Metatag
|
||||
Desc: Return all children of a metatag in an array.
|
||||
#*/
|
||||
sq_register(vm, MetatagGetChildren, "MetatagGetChildren", _SC(".x"));
|
||||
|
||||
// Push defines.
|
||||
sq_pushroottable(vm);
|
||||
|
||||
/*#
|
||||
Enum: TagType
|
||||
Values: TagTypeBinary,TagTypeString,TagTypeInteger,TagTypeReal,TagTypeNode,TagTypeNone
|
||||
#*/
|
||||
sq_pushstring(vm, "TagTypeBinary", -1); sq_pushinteger(vm, GS::Variant::VariantBinary); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "TagTypeInteger", -1); sq_pushinteger(vm, GS::Variant::VariantInteger); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "TagTypeNone", -1); sq_pushinteger(vm, GS::Variant::VariantNone); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "TagTypeReal", -1); sq_pushinteger(vm, GS::Variant::VariantFloat); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "TagTypeString", -1); sq_pushinteger(vm, GS::Variant::VariantString); sq_newslot(vm, -3, true);
|
||||
#if 1
|
||||
sq_pushstring(vm, "TagTypeNode", -1); sq_pushinteger(vm, GS::Variant::VariantNone); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "TagTypeTag", -1); sq_pushinteger(vm, GS::Variant::VariantNone); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "TagTypeShortcut", -1); sq_pushinteger(vm, GS::Variant::VariantNone); sq_newslot(vm, -3, true);
|
||||
#endif
|
||||
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
217
include/modules/script_squirrel/legacy/object_binding.cpp
Normal file
217
include/modules/script_squirrel/legacy/object_binding.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "script_squirrel/legacy/binding_helpers.h"
|
||||
#include "scene3d/mobject.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
static CObjectType object_derived_types[] = { typetag_Item, typetag_Object, typetag_Undefined };
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ObjectGetLODBias(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_RETURNFLOAT(GS::Core::Object::lod_bias)
|
||||
}
|
||||
SQInteger ObjectSetLODBias(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETFLOAT(bias))
|
||||
GS::Core::Object::lod_bias = bias;
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------
|
||||
SQInteger ObjectGetItem(HSQUIRRELVM vm)
|
||||
//-----------------------------------------------
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(obj, MObject, typetag_Object)
|
||||
__SQ_RETURNSAFEPTR((MItem *)obj, typetag_Item)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#define __SQ_ASSERTRENDERDATA(__I__) if (__I__->render_data.IsNull()) return sq_throwerror(vm, "No render data, have you setup this item render data?");
|
||||
|
||||
SQInteger ObjectSetGeometry(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(o, MObject, object_derived_types)
|
||||
__SQ_GETSAFEPTRALLOWNULL(geo, GS::Render::Geometry, typetag_Geometry)
|
||||
__SQ_GETEND
|
||||
__SQ_ASSERTRENDERDATA(o)
|
||||
o->geometry = geo ? geo->name : NULL;
|
||||
o->render_data->geometry = geo;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ObjectGetGeometry(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(o, MObject, object_derived_types))
|
||||
__SQ_ASSERTRENDERDATA(o)
|
||||
__SQ_RETURNSAFEPTR(o->render_data->geometry.c_ptr(), typetag_Geometry)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ObjectSkinGetItemCount(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(o, MObject, object_derived_types))
|
||||
__SQ_RETURNINT(o->GetBoneCount())
|
||||
}
|
||||
SQInteger ObjectSkinGetItem(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(o, MObject, object_derived_types)
|
||||
__SQ_GETINT(n)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(o->GetBone(n) ? o->GetBone(n)->mitem : NULL, typetag_Item)
|
||||
}
|
||||
SQInteger ObjectSkinSetItem(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETCOBJECTBASE(o, MObject, object_derived_types)
|
||||
__SQ_GETINT(n)
|
||||
__SQ_GETSAFEPTRALLOWNULL(b, MItem, typetag_Item)
|
||||
__SQ_GETEND
|
||||
o->BindBone(n, b ? b->GetBaseItem() : NULL);
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ObjectSetSkinMotion(HSQUIRRELVM vm)
|
||||
{
|
||||
/*
|
||||
__SQ_GETSTART(6)
|
||||
__SQ_GETSAFEPTR(obj, MObject, typetag_Object)
|
||||
__SQ_GETSTRING(motion_id)
|
||||
__SQ_GETFLOAT(blend)
|
||||
__SQ_GETFLOAT(weight)
|
||||
__SQ_GETFLOAT(t)
|
||||
__SQ_GETBOOL(loop)
|
||||
nHierarchyMotion *mot = (nHierarchyMotion *)obj->skin_motion_list.Find(motion_id);
|
||||
if (obj && mot)
|
||||
SetHierarchyMotion(obj->GetSkin(), mot, blend, weight, t, loop ? true : false);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
*/
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(o, MObject, object_derived_types)
|
||||
__SQ_GETSTRING(motion_name)
|
||||
|
||||
// obj->SetSkinMotion(motion_name);
|
||||
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ObjectSetSkinMotionClockScale(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETCOBJECTBASE(o, MObject, object_derived_types)
|
||||
__SQ_GETFLOAT(scale)
|
||||
__SQ_GETEND
|
||||
return 0;
|
||||
}
|
||||
SQInteger ObjectStopAllSkinMotion(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETCOBJECTBASE(o, MObject, object_derived_types))
|
||||
// if (obj)
|
||||
// StopAllHierarchyMotion(obj->GetSkin());
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterObjectBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Object
|
||||
Type: Object
|
||||
Related: Item
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: ObjectGeneric
|
||||
Desc: Generic functions
|
||||
#*/
|
||||
/*#
|
||||
Func: ObjectGetItem
|
||||
Proto: Item:Object
|
||||
Desc: Get object item.
|
||||
#*/
|
||||
sq_register(vm, ObjectGetItem, "ObjectGetItem", _SC(".x"));
|
||||
/*#
|
||||
Func: ObjectSetGeometry
|
||||
Proto: void:Object,Geometry
|
||||
Desc: Set object geometry.
|
||||
#*/
|
||||
sq_register(vm, ObjectSetGeometry, "ObjectSetGeometry", _SC(".xx"));
|
||||
/*#
|
||||
Func: ObjectGetGeometry
|
||||
Proto: Geometry:Object
|
||||
Desc: Get geometry object.
|
||||
#*/
|
||||
sq_register(vm, ObjectGetGeometry, "ObjectGetGeometry", _SC(".x"));
|
||||
/*#
|
||||
Func: ObjectGetLODBias
|
||||
Proto: float:
|
||||
Desc: Get global object geometry lod bias.
|
||||
Note: This value is added to the distance used to select the lod level for a geometry before displaying it.
|
||||
#*/
|
||||
sq_register(vm, ObjectGetLODBias, "ObjectGetLODBias", _SC("."));
|
||||
/*#
|
||||
Func: ObjectSetLODBias
|
||||
Proto: void:float bias
|
||||
Desc: Set global object geometry lod bias.
|
||||
Note: This value is added to the distance used to select the lod level for a geometry before displaying it.
|
||||
Example: ObjectSetLODBias(Mtr(10.0)) // Push all geometry LODs back by 10 meters.
|
||||
#*/
|
||||
sq_register(vm, ObjectSetLODBias, "ObjectSetLODBias", _SC(".n"));
|
||||
|
||||
/*#
|
||||
Section: ObjectSkin
|
||||
Desc: Skin functions
|
||||
#*/
|
||||
/*#
|
||||
Func: ObjectSkinGetItemCount
|
||||
Proto: int:Object
|
||||
Desc: Return the number of bone items in the object skin.
|
||||
#*/
|
||||
sq_register(vm, ObjectSkinGetItemCount, "ObjectSkinGetItemCount", _SC(".x"));
|
||||
/*#
|
||||
Func: ObjectSkinGetItem
|
||||
Proto: Item:Object,int index
|
||||
Desc: Return a bone item from the object skin.
|
||||
#*/
|
||||
sq_register(vm, ObjectSkinGetItem, "ObjectSkinGetItem", _SC(".xi"));
|
||||
/*#
|
||||
Func: ObjectSkinSetItem
|
||||
Proto: void:Object,int index,Item bone
|
||||
Desc: Set a bone item in the object skin.
|
||||
#*/
|
||||
sq_register(vm, ObjectSkinSetItem, "ObjectSkinSetItem", _SC(".xix"));
|
||||
|
||||
/*#
|
||||
Func: ObjectSetSkinMotion
|
||||
Proto: void:Object,string name
|
||||
Desc: Set object skin motion.
|
||||
#*/
|
||||
sq_register(vm, ObjectSetSkinMotion, "ObjectSetSkinMotion", _SC(".xs"));
|
||||
/*#
|
||||
Func: ObjectSetSkinMotionClockScale
|
||||
Proto: void:Object,float scale
|
||||
Desc: Set current object skin motion clock scale.
|
||||
#*/
|
||||
sq_register(vm, ObjectSetSkinMotionClockScale, "ObjectSetSkinMotionClockScale", _SC(".xf"));
|
||||
/*#
|
||||
Func: ObjectStopAllSkinMotion
|
||||
Proto: void:Object
|
||||
Desc: Stop all object skin motions.
|
||||
#*/
|
||||
sq_register(vm, ObjectStopAllSkinMotion, "ObjectStopAllSkinMotion", _SC(".x"));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
222
include/modules/script_squirrel/legacy/peer_network_binding.cpp
Normal file
222
include/modules/script_squirrel/legacy/peer_network_binding.cpp
Normal file
@ -0,0 +1,222 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "squirrel_binding.h"
|
||||
#include "script/script_variant.h"
|
||||
#include "async/async_call_queue_thread.h"
|
||||
#include "binding_helpers.h"
|
||||
#include "sqstdblob.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
#if __PLATFORM_EMSCRIPTEN__ == 0
|
||||
|
||||
#include "network_enet/enet_network.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct ScriptPeerThread : public Network::Enet, public Threading::ASyncCallQueueThread
|
||||
{
|
||||
void OnIdle()
|
||||
{ UpdateHost(); }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
struct VMThreadData
|
||||
{
|
||||
SquirrelVM *vm;
|
||||
|
||||
void OnPeerConnection(void *peer)
|
||||
{
|
||||
if (peer && vm->SetupFunctionCall("OnPeerConnection"))
|
||||
{
|
||||
vm->PushVariant(Script::Variant(peer, typetag_Peer));
|
||||
vm->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
void OnPacketReceived(void *peer, const Array <char> &packet)
|
||||
{
|
||||
if (peer && vm->SetupFunctionCall("OnPacketReceived"))
|
||||
{
|
||||
vm->PushVariant(Script::Variant(peer, typetag_Peer));
|
||||
vm->PushVariant(Script::Variant((const void *)packet.c_ptr(), packet.GetSize()));
|
||||
vm->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
void OnConnectionClosed(void *peer)
|
||||
{
|
||||
if (peer && vm->SetupFunctionCall("OnConnectionClosed"))
|
||||
{
|
||||
vm->PushVariant(Script::Variant(peer, typetag_Peer));
|
||||
vm->DoFunctionCall();
|
||||
}
|
||||
}
|
||||
|
||||
// To be executed from the VM thread.
|
||||
ASync::CallQueue task_queue;
|
||||
|
||||
VMThreadData(SquirrelVM *v) : vm(v) {}
|
||||
};
|
||||
|
||||
VMThreadData vm_thread;
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void OnPeerConnection(void *peer)
|
||||
{ vm_thread.task_queue.QueueMemberCall(&vm_thread, &VMThreadData::OnPeerConnection, peer); }
|
||||
void OnPacketReceived(void *peer, const void *data, size_t size)
|
||||
{ vm_thread.task_queue.QueueMemberCall(&vm_thread, &VMThreadData::OnPacketReceived, peer, Array <char> (size, (const char *)data)); }
|
||||
void OnConnectionClosed(void *peer)
|
||||
{ vm_thread.task_queue.QueueMemberCall(&vm_thread, &VMThreadData::OnConnectionClosed, peer); }
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
ScriptPeerThread(SquirrelVM *v) : vm_thread(v) {}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PeerNetOpenServer(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSTRING(ip)
|
||||
__SQ_GETINT(port)
|
||||
__SQ_GETEND
|
||||
|
||||
ScriptPeerThread *t = new ScriptPeerThread(GetVMObject(vm));
|
||||
if (t == NULL)
|
||||
return sq_throwerror(vm, "Failed to allocate peer network controller.");
|
||||
|
||||
t->Start();
|
||||
t->QueueMemberCall(t, &ScriptPeerThread::OpenServer, String(ip), port);
|
||||
|
||||
__SQ_RETURNMANAGEDSAFEPTR(t, typetag_PeerController)
|
||||
}
|
||||
SQInteger PeerNetOpenClient(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSTRING(ip)
|
||||
__SQ_GETINT(port)
|
||||
__SQ_GETEND
|
||||
|
||||
ScriptPeerThread *t = new ScriptPeerThread(GetVMObject(vm));
|
||||
if (t == NULL)
|
||||
return sq_throwerror(vm, "Failed to allocate peer network controller.");
|
||||
|
||||
t->Start();
|
||||
t->QueueMemberCall(t, &ScriptPeerThread::OpenClient, String(ip), port);
|
||||
|
||||
__SQ_RETURNMANAGEDSAFEPTR(t, typetag_PeerController)
|
||||
}
|
||||
SQInteger PeerNetUpdate(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(t, ScriptPeerThread, typetag_PeerController)
|
||||
t->vm_thread.task_queue.ExecuteAll();
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PeerNetSendString(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(t, ScriptPeerThread, typetag_PeerController)
|
||||
__SQ_GETSAFEPTR(peer, ENetPeer *, typetag_Peer)
|
||||
__SQ_GETSTRING(data)
|
||||
__SQ_GETEND
|
||||
t->QueueMemberCall(t, &ScriptPeerThread::SendString, peer, String(data));
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PeerNetBroadcastString(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(t, ScriptPeerThread, typetag_PeerController)
|
||||
__SQ_GETSTRING(data)
|
||||
__SQ_GETEND
|
||||
t->QueueMemberCall(t, &ScriptPeerThread::BroadcastString, String(data));
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#else
|
||||
|
||||
SQInteger PeerNetOpenServer(HSQUIRRELVM vm)
|
||||
{ return 0; }
|
||||
SQInteger PeerNetOpenClient(HSQUIRRELVM vm)
|
||||
{ return 0; }
|
||||
SQInteger PeerNetUpdate(HSQUIRRELVM vm)
|
||||
{ return 0; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PeerNetSendString(HSQUIRRELVM vm)
|
||||
{ return 0; }
|
||||
SQInteger PeerNetBroadcastString(HSQUIRRELVM vm)
|
||||
{ return 0; }
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterINetBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Peer Network
|
||||
Desc: Implement a peer-to-peer network.
|
||||
Type: PeerController
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: PeerNetHandshake
|
||||
Desc: Handshaking
|
||||
#*/
|
||||
/*#
|
||||
Func: PeerNetOpenServer
|
||||
Proto: PeerController:String ip,int port
|
||||
Desc: Open a listening server connection on a given ip address and port.
|
||||
Note: A server connection is usually opened on the local host ip "127.0.0.1".
|
||||
Example:
|
||||
// Start a peer server on the local host on port 8000.
|
||||
PeerNetOpenServer("127.0.0.1", 8000)
|
||||
#*/
|
||||
sq_register(vm, PeerNetOpenServer, "PeerNetOpenServer", _SC(".si"));
|
||||
/*#
|
||||
Func: PeerNetOpenClient
|
||||
Proto: PeerController:String ip,int port
|
||||
Desc: Open a client connection to a given ip address and port.
|
||||
Example:
|
||||
// Connect client to peer server on the remote address 192.168.0.12 on port 8000.
|
||||
PeerNetOpenClient("192.168.0.12", 8000)
|
||||
#*/
|
||||
sq_register(vm, PeerNetOpenClient, "PeerNetOpenClient", _SC(".ss"));
|
||||
/*#
|
||||
Section: PeerNetCommunication
|
||||
Desc: Communication
|
||||
#*/
|
||||
/*#
|
||||
Func: PeerNetSendString
|
||||
Proto: void:PeerController controller,Peer peer,String data
|
||||
Desc: Send a string to a specific peer controller.
|
||||
Example:
|
||||
// Send the HELLO string to a specific peer.
|
||||
PeerNetSendString(controller, peer, "HELLO")
|
||||
#*/
|
||||
sq_register(vm, PeerNetSendString, "PeerNetSendString", _SC(".xxs"));
|
||||
/*#
|
||||
Func: PeerNetBroadcastString
|
||||
Proto: void:PeerController controller,String data
|
||||
Desc: Send a string to all peer controllers connected to this controller.
|
||||
Example:
|
||||
// Broadcast the HELLO string to all connected peers.
|
||||
PeerNetBroadcastString(controller, "HELLO")
|
||||
#*/
|
||||
sq_register(vm, PeerNetBroadcastString, "PeerNetBroadcastString", _SC(".xs"));
|
||||
/*#
|
||||
Func: PeerNetUpdate
|
||||
Proto: void:PeerController controller
|
||||
Desc: Dispatch all pending network events for a controller to the global handler functions.
|
||||
#*/
|
||||
sq_register(vm, PeerNetUpdate, "PeerNetUpdate", _SC(".x"));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
448
include/modules/script_squirrel/legacy/physic_binding.cpp
Normal file
448
include/modules/script_squirrel/legacy/physic_binding.cpp
Normal file
@ -0,0 +1,448 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "squirrel.h"
|
||||
#include "binding_helpers.h"
|
||||
#include "physic/physic_constraint.h"
|
||||
#include "physic/physic_world.h"
|
||||
#include "scene3d/mconstraint.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "math/matrix4.h"
|
||||
#include "math/vector.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger SceneAddConstraint(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(s, Scene, typetag_Scene3d)
|
||||
__SQ_GETSTRING(name)
|
||||
if (!s->physic_world)
|
||||
return sq_throwerror(vm, "Cannot create constraint, no physic world in scene.");
|
||||
MConstraint *c = new MConstraint(s->physic_world->NewConstraint());
|
||||
if (!c)
|
||||
return sq_throwerror(vm, "Failed to allocate constraint.");
|
||||
c->name = name;
|
||||
s->AddItem(c, true);
|
||||
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(c, typetag_Constraint)
|
||||
}
|
||||
SQInteger SceneAddPointConstraint(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(6)
|
||||
__SQ_GETSAFEPTR(s, Scene, typetag_Scene3d)
|
||||
__SQ_GETSTRING(name)
|
||||
__SQ_GETSAFEPTR(a, MItem, typetag_Item)
|
||||
__SQ_GETSAFEPTR(b, MItem, typetag_Item)
|
||||
__SQ_GETVECTOR(pivot_a)
|
||||
__SQ_GETVECTOR(pivot_b)
|
||||
|
||||
if (!s->physic_world)
|
||||
return sq_throwerror(vm, "Cannot create constraint, no physic world in scene.");
|
||||
MConstraint *c = new MConstraint(s->physic_world->NewConstraint());
|
||||
if (!c)
|
||||
return sq_throwerror(vm, "Failed to allocate constraint.");
|
||||
c->name = name;
|
||||
s->AddItem(c, true);
|
||||
|
||||
if (!a->physic_item || !b->physic_item)
|
||||
return sq_throwerror(vm, "Item has no physics component.");
|
||||
|
||||
c->desc.type = PhysicConstraintDesc::TypePoint;
|
||||
c->desc.item_a = a;
|
||||
c->desc.item_b = b;
|
||||
c->desc.pivot_a = GS::Matrix4::TranslationMatrix(pivot_a);
|
||||
c->desc.pivot_b = GS::Matrix4::TranslationMatrix(pivot_b);
|
||||
|
||||
c->Setup(s->physic_world);
|
||||
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(c, typetag_Constraint)
|
||||
}
|
||||
SQInteger SceneAddPointConstraintHinge(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(6)
|
||||
__SQ_GETSAFEPTR(s, Scene, typetag_Scene3d)
|
||||
__SQ_GETSTRING(name)
|
||||
__SQ_GETSAFEPTR(a, MItem, typetag_Item)
|
||||
__SQ_GETSAFEPTR(b, MItem, typetag_Item)
|
||||
__SQ_GETVECTOR(pivot_a)
|
||||
__SQ_GETVECTOR(pivot_b)
|
||||
|
||||
if (!s->physic_world)
|
||||
return sq_throwerror(vm, "Cannot create constraint, no physic world in scene.");
|
||||
MConstraint *c = new MConstraint(s->physic_world->NewConstraint());
|
||||
if (!c)
|
||||
return sq_throwerror(vm, "Failed to allocate constraint.");
|
||||
c->name = name;
|
||||
s->AddItem(c, true);
|
||||
|
||||
if (!a->physic_item || !b->physic_item)
|
||||
return sq_throwerror(vm, "Item has no physics component.");
|
||||
|
||||
c->desc.type = PhysicConstraintDesc::TypeHinge;
|
||||
c->desc.item_a = a;
|
||||
c->desc.item_b = b;
|
||||
c->desc.pivot_a = GS::Matrix4::TranslationMatrix(pivot_a);
|
||||
c->desc.pivot_b = GS::Matrix4::TranslationMatrix(pivot_b);
|
||||
|
||||
c->Setup(s->physic_world);
|
||||
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(c, typetag_Constraint)
|
||||
}
|
||||
SQInteger ConstraintEnable(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(c, MConstraint, typetag_Constraint)
|
||||
__SQ_GETBOOL(b)
|
||||
__SQ_GETEND
|
||||
if (c->physic_data.IsValid())
|
||||
c->physic_data->Enable(asbool(b));
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ConstraintGetPivotA(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(c, MConstraint, typetag_Constraint)
|
||||
__SQ_RETURNVECTOR(c->desc.pivot_a.GetRow(3))
|
||||
}
|
||||
SQInteger ConstraintGetPivotB(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(c, MConstraint, typetag_Constraint)
|
||||
__SQ_RETURNVECTOR(c->desc.pivot_b.GetRow(3))
|
||||
}
|
||||
SQInteger ConstraintSetPivotA(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(c, MConstraint, typetag_Constraint)
|
||||
__SQ_GETVECTOR(pivot)
|
||||
__SQ_GETEND
|
||||
c->desc.pivot_a = GS::Matrix4::TranslationMatrix(pivot);
|
||||
c->physic_data->SetPivotA(c->desc.pivot_a);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ConstraintSetPivotB(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(c, MConstraint, typetag_Constraint)
|
||||
__SQ_GETVECTOR(pivot)
|
||||
__SQ_GETEND
|
||||
c->desc.pivot_b = GS::Matrix4::TranslationMatrix(pivot);
|
||||
c->physic_data->SetPivotB(c->desc.pivot_b);
|
||||
__SQ_RETURN
|
||||
}
|
||||
#include "physic_bullet/bullet_constraint.h"
|
||||
SQInteger ConstraintSetLimit(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(6)
|
||||
__SQ_GETSAFEPTR(c, MConstraint, typetag_Constraint)
|
||||
__SQ_GETFLOAT(low)
|
||||
__SQ_GETFLOAT(high)
|
||||
__SQ_GETFLOAT(softness)
|
||||
__SQ_GETFLOAT(biasfactor)
|
||||
__SQ_GETFLOAT(relaxationFactor)
|
||||
__SQ_GETEND
|
||||
((BulletConstraint*)(c->physic_data.c_ptr()))->setLimitHinge(low, high, softness, biasfactor, relaxationFactor);
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ConstraintGetItem(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(c, MConstraint, typetag_Constraint)
|
||||
__SQ_RETURNSAFEPTR((MItem *)c, typetag_Item)
|
||||
}
|
||||
SQInteger ConstraintSetItemA(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(c, MConstraint, typetag_Constraint)
|
||||
__SQ_GETSAFEPTR(i, MItem, typetag_Item)
|
||||
__SQ_GETEND
|
||||
c->desc.item_a = i;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ConstraintSetItemB(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(c, MConstraint, typetag_Constraint)
|
||||
__SQ_GETSAFEPTR(i, MItem, typetag_Item)
|
||||
__SQ_GETEND
|
||||
c->desc.item_b = i;
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
#include "script_squirrel/mmf.h"
|
||||
|
||||
// See TELEMETRY_DATA.flags
|
||||
#define MMF_CONFIG_EXPLICIT_LOCAL_VEL 1
|
||||
#define MMF_CONFIG_EXPLICIT_LOCAL_ACCEL 2
|
||||
#define MMF_CONFIG_EXPLICIT_GLOBAL_ACCEL 4
|
||||
#define MMF_CONFIG_EXPLICIT_ACCEL_EXCLUDES_GRAVITY 8
|
||||
|
||||
// See TELEMETRY_DATA.flags
|
||||
#define CONFIG_EXPLICIT_LOCAL_VEL (1 << 0)
|
||||
#define CONFIG_EXPLICIT_LOCAL_ACCEL (1 << 1)
|
||||
#define CONFIG_EXPLICIT_ACCEL_EXCLUDES_GRAVITY (1 << 3)
|
||||
#define CONFIG_ROW_ORDERED_MATRIX (1 << 4)
|
||||
|
||||
// See TELEMETRY_DATA.axis
|
||||
#define AXIS_X_UP (1 << 0)
|
||||
#define AXIS_X_DOWN (1 << 1)
|
||||
#define AXIS_X_NORTH (1 << 2)
|
||||
#define AXIS_X_SOUTH (1 << 3)
|
||||
#define AXIS_X_EAST (1 << 4)
|
||||
#define AXIS_X_WEST (1 << 5)
|
||||
#define AXIS_Y_UP (1 << 8)
|
||||
#define AXIS_Y_DOWN (1 << 9)
|
||||
#define AXIS_Y_NORTH (1 << 10)
|
||||
#define AXIS_Y_SOUTH (1 << 11)
|
||||
#define AXIS_Y_EAST (1 << 12)
|
||||
#define AXIS_Y_WEST (1 << 13)
|
||||
#define AXIS_Z_UP (1 << 16)
|
||||
#define AXIS_Z_DOWN (1 << 17)
|
||||
#define AXIS_Z_NORTH (1 << 18)
|
||||
#define AXIS_Z_SOUTH (1 << 19)
|
||||
#define AXIS_Z_EAST (1 << 20)
|
||||
#define AXIS_Z_WEST (1 << 21)
|
||||
|
||||
|
||||
struct TELEMETRY_DATA
|
||||
{
|
||||
unsigned int flags;
|
||||
unsigned int axis;
|
||||
float accel[3];
|
||||
float vel[3];
|
||||
float rotationMatrix[3][3];
|
||||
DWORD packetTimeMillis;
|
||||
};
|
||||
/*
|
||||
struct SIMPHYNITYMMF
|
||||
{
|
||||
unsigned char flags;
|
||||
DWORD packetTime;
|
||||
float telemetryMatrix[16];
|
||||
float velocity[3];
|
||||
float accel[3];
|
||||
};*/
|
||||
struct SIMPHYNITYMMF
|
||||
{
|
||||
DWORD packetTime;
|
||||
float telemetryMatrix[16];
|
||||
float globalVelocity[3];
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
SQInteger CreateMMF(HSQUIRRELVM vm)
|
||||
//-------------------------------------------------------
|
||||
{
|
||||
__SQ_RETURNSAFEPTR(new CMMF(_T("$SIMPHYNITYTELEM$"), sizeof(TELEMETRY_DATA), _T("$SIMPHYNITYTELEMMUTEX$")), typetag_Item)
|
||||
// __SQ_RETURNSAFEPTR(new CMMF(_T("$SIMPHYNITYTELEM$"), sizeof(SIMPHYNITYMMF), _T("$SIMPHYNITYTELEMMUTEX$")), typetag_Item)
|
||||
}
|
||||
#define __SQ_GETPHYSICITEM(__I__) PhysicItem *iphysic = (__I__)->physic_item.c_ptr(); if (!iphysic) return sq_throwerror(vm, "No physics found, did you setup this item?");
|
||||
//-------------------------------------------------------
|
||||
SQInteger UpdateMMF(HSQUIRRELVM vm)
|
||||
//-------------------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(mmf, CMMF, typetag_Item)
|
||||
__SQ_GETSAFEPTR(item, MItem, typetag_Item)
|
||||
__SQ_GETFLOAT(Physic_T)
|
||||
__SQ_GETEND
|
||||
|
||||
__SQ_GETPHYSICITEM(item)
|
||||
|
||||
GS::Matrix4 item_matrix;
|
||||
iphysic->GetMatrix(item_matrix);
|
||||
item_matrix = item->GetBaseItem()->GetMatrix();
|
||||
|
||||
GS::Vector4 position;
|
||||
GS::Vector4 scale;
|
||||
GS::Matrix3 rotation;
|
||||
item_matrix.Decompose(&position, &scale, &rotation);
|
||||
|
||||
// GS::Vector4 velocity_vec = (item && item->isActive() ? iphysic->GetLinearVelocity() : GS::Vector4(0, 0, 0));
|
||||
GS::Vector4 velocity_vec = (item && item->isActive() ? iphysic->GetLinearVelocity() : GS::Vector4(0, 0, 0));
|
||||
/*
|
||||
|
||||
SIMPHYNITYMMF m_Telem;
|
||||
m_Telem.packetTime = Physic_T*1000.0f; // Current physics time.
|
||||
memcpy(m_Telem.telemetryMatrix, item_matrix.m, sizeof(m_Telem.telemetryMatrix)); // Current rotation, position.
|
||||
memcpy(m_Telem.globalVelocity, ((float *)&(velocity_vec.x)), sizeof(m_Telem.globalVelocity)); // Global vel XYZ.
|
||||
mmf->Write(&m_Telem);
|
||||
*/
|
||||
|
||||
TELEMETRY_DATA m_Telem;
|
||||
m_Telem.packetTimeMillis = Physic_T*1000.0f; // Current physics time.
|
||||
m_Telem.axis = AXIS_X_EAST | AXIS_Y_UP | AXIS_Z_NORTH;
|
||||
m_Telem.flags = CONFIG_EXPLICIT_LOCAL_VEL | CONFIG_EXPLICIT_ACCEL_EXCLUDES_GRAVITY | CONFIG_ROW_ORDERED_MATRIX;
|
||||
memcpy(m_Telem.rotationMatrix, rotation.m, sizeof(m_Telem.rotationMatrix)); // Current rotation
|
||||
memcpy(m_Telem.vel, ((float *)&(velocity_vec.x)), sizeof(m_Telem.vel)); // Global vel XYZ.
|
||||
m_Telem.accel[0] = 0; m_Telem.accel[1] = 0; m_Telem.accel[2] = 0;
|
||||
mmf->Write(&m_Telem);
|
||||
|
||||
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------
|
||||
struct ENGINE_TELEMETRY_DATA
|
||||
{
|
||||
char package[32768];
|
||||
};
|
||||
|
||||
SQInteger CreateEngineMMF(HSQUIRRELVM vm)
|
||||
//-------------------------------------------------------
|
||||
{
|
||||
__SQ_RETURNSAFEPTR(new CMMF(_T("$DevelterInnovationSimulateur$"), sizeof(ENGINE_TELEMETRY_DATA), _T("$DevelterInnovationSimulateurMUTEX$")), typetag_Item)
|
||||
}
|
||||
//-------------------------------------------------------
|
||||
SQInteger UpdateEngineMMF(HSQUIRRELVM vm)
|
||||
//-------------------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(mmf, CMMF, typetag_Item)
|
||||
__SQ_GETSTRING(package)
|
||||
__SQ_GETEND
|
||||
|
||||
GS::String spackage(package);
|
||||
|
||||
if (spackage.Size() > 32768)
|
||||
return sq_throwerror(vm, "UpdateEngineMMF: package bigger than 16384 bits.");
|
||||
|
||||
ENGINE_TELEMETRY_DATA m_Telem;
|
||||
memset(m_Telem.package, 0, 32768);
|
||||
memcpy(m_Telem.package, spackage.c_str(), spackage.Size());
|
||||
mmf->Write(&m_Telem);
|
||||
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterPhysicBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Physic
|
||||
Type: Constraint
|
||||
Desc: Physic world functions. For item related physic functions please refer to the Item topic.
|
||||
Related: Item
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Func: CreateMMF
|
||||
Proto: MMF:void
|
||||
Desc: Create mmf object for simu purpose.
|
||||
#*/
|
||||
sq_register(vm, CreateMMF, "CreateMMF", _SC("."));
|
||||
/*#
|
||||
Func: UpdateMMF
|
||||
Proto: void:MMF, ,
|
||||
Desc: update the mmf with the object rotation and velocity.
|
||||
#*/
|
||||
sq_register(vm, UpdateMMF, "UpdateMMF", _SC(".xxf"));
|
||||
|
||||
/*#
|
||||
Func: CreateEngineMMF
|
||||
Proto: MMF:void
|
||||
Desc: Create mmf object for simu purpose.
|
||||
#*/
|
||||
sq_register(vm, CreateEngineMMF, "CreateEngineMMF", _SC("."));
|
||||
/*#
|
||||
Func: UpdateEngineMMF
|
||||
Proto: void:MMF
|
||||
Desc: update the mmf with the json values
|
||||
#*/
|
||||
sq_register(vm, UpdateEngineMMF, "UpdateEngineMMF", _SC(".xs"));
|
||||
/*#
|
||||
Section: ConstraintManagement
|
||||
Desc: Constraint management functions
|
||||
#*/
|
||||
/*#
|
||||
Func: SceneAddPointConstraint
|
||||
Proto: Constraint:Scene,string name, Item a,Item b,Vector pivot_a,Vector pivot_b
|
||||
Desc: Create a new point constraint between two items. The pivot position is in item space. The null item can be set as item B to specify an unmovable world space hook.
|
||||
#*/
|
||||
sq_register(vm, SceneAddPointConstraint, "SceneAddPointConstraint", _SC(".xsxxxx"));
|
||||
/*#
|
||||
Func: SceneAddPointConstraintHinge
|
||||
Proto: Constraint:Scene,string name, Item a,Item b,Vector pivot_a,Vector pivot_b
|
||||
Desc: Create a new point constraint between two items. The pivot position is in item space. The null item can be set as item B to specify an unmovable world space hook.
|
||||
#*/
|
||||
sq_register(vm, SceneAddPointConstraintHinge, "SceneAddPointConstraintHinge", _SC(".xsxxxx"));
|
||||
|
||||
/*#
|
||||
Func: ConstraintEnable
|
||||
Proto: void:Constraint,bool
|
||||
Desc: Enable/disable constraint.
|
||||
#*/
|
||||
sq_register(vm, ConstraintEnable, "ConstraintEnable", _SC(".xb"));
|
||||
|
||||
/*#
|
||||
Section: ConstraintConfiguration
|
||||
Desc: Constraint configuration functions
|
||||
#*/
|
||||
/*#
|
||||
Func: ConstraintGetPivotA
|
||||
Proto: Vector:Constraint
|
||||
Desc: Get the constraint item A pivot vector.
|
||||
#*/
|
||||
sq_register(vm, ConstraintGetPivotA, "ConstraintGetPivotA", _SC(".x"));
|
||||
/*#
|
||||
Func: ConstraintGetPivotB
|
||||
Proto: Vector:Constraint
|
||||
Desc: Get the constraint item B pivot vector.
|
||||
#*/
|
||||
sq_register(vm, ConstraintGetPivotB, "ConstraintGetPivotB", _SC(".x"));
|
||||
/*#
|
||||
Func: ConstraintSetPivotA
|
||||
Proto: void:Constraint,Vector pivot
|
||||
Desc: Set the constraint item A pivot vector.
|
||||
#*/
|
||||
sq_register(vm, ConstraintSetPivotA, "ConstraintSetPivotA", _SC(".xx"));
|
||||
/*#
|
||||
Func: ConstraintSetPivotB
|
||||
Proto: void:Constraint,Vector pivot
|
||||
Desc: Set the constraint item B pivot vector.
|
||||
#*/
|
||||
sq_register(vm, ConstraintSetPivotB, "ConstraintSetPivotB", _SC(".xx"));
|
||||
/*#
|
||||
Func: ConstraintSetLimit
|
||||
Proto: void:Constraint,float low, float high, float softness, float biasfactor, float relaxationfactor
|
||||
Desc: Set the constraint limit.
|
||||
#*/
|
||||
sq_register(vm, ConstraintSetLimit, "ConstraintSetLimit", _SC(".xfffff"));
|
||||
|
||||
/*#
|
||||
Func: ConstraintGetItem
|
||||
Proto: Item:Constraint
|
||||
Desc: Get constraint item.
|
||||
#*/
|
||||
sq_register(vm, ConstraintGetItem, "ConstraintGetItem", _SC(".x"));
|
||||
/*#
|
||||
Func: ConstraintSetItemA
|
||||
Proto: void:Constraint,Item
|
||||
Desc: Set constraint item A.
|
||||
#*/
|
||||
sq_register(vm, ConstraintSetItemA, "ConstraintSetItemA", _SC(".xx"));
|
||||
/*#
|
||||
Func: ConstraintSetItemB
|
||||
Proto: void:Constraint,Item
|
||||
Desc: Set constraint item B.
|
||||
#*/
|
||||
sq_register(vm, ConstraintSetItemB, "ConstraintSetItemB", _SC(".xx"));
|
||||
|
||||
// Push defines.
|
||||
sq_pushroottable(vm);
|
||||
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
515
include/modules/script_squirrel/legacy/picture_binding.cpp
Normal file
515
include/modules/script_squirrel/legacy/picture_binding.cpp
Normal file
@ -0,0 +1,515 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "ui/ui.h"
|
||||
#include "font/font_renderer.h"
|
||||
#include "picture/pict_io.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
void IterateTextParameters(HSQUIRRELVM vm, int idx, TextState &state);
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger NewPicture(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETINT(w)
|
||||
__SQ_GETINT(h)
|
||||
__SQ_GETEND
|
||||
Picture *p = new Picture;
|
||||
if (!p || !p->AllocAs(w, h))
|
||||
return sq_throwerror(vm, String::Format("Failed to allocate a new %dx%d picture.", w, h));
|
||||
__SQ_RETURNSAFEPTR(p, typetag_Picture)
|
||||
}
|
||||
SQInteger LoadPicture(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(path)
|
||||
Picture *p = new Picture;
|
||||
if (!p)
|
||||
return sq_throwerror(vm, "Failed to allocate picture.");
|
||||
if (!PictureIO::Get().Load(*p, path))
|
||||
return sq_throwerror(vm, String::Format("Failed to load picture '%s'.", path));
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(p, typetag_Picture)
|
||||
}
|
||||
SQInteger PictureClone(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(p, Picture, typetag_Picture)
|
||||
__SQ_RETURNSAFEPTR(new Picture(*p), typetag_Picture);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
SQInteger PictureWriteText(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(5)
|
||||
__SQ_GETSAFEPTR(p, Picture, typetag_Picture)
|
||||
__SQ_GETRECT(out_rect)
|
||||
__SQ_GETSTRING(text)
|
||||
__SQ_GETSAFEPTR(font, FontEx, typetag_Font)
|
||||
|
||||
TextState state;
|
||||
IterateTextParameters(vm, -1, state);
|
||||
__SQ_GETUPDATESTACK
|
||||
|
||||
state.font = font;
|
||||
|
||||
iRect clip_rect = p->GetRect();
|
||||
FontRenderer::Format(text, state, out_rect);
|
||||
FontRenderer::Compose(*p, text, state, out_rect, clip_rect);
|
||||
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
SQInteger PictureApplyConvolution(HSQUIRRELVM vm)
|
||||
{
|
||||
Picture *pic;
|
||||
if (!CObject::Get(vm, -6, (void **)&pic, typetag_Picture))
|
||||
return -1;
|
||||
if (!pic)
|
||||
return sq_throwerror(vm, "Invalid picture.");
|
||||
|
||||
// Kernel size.
|
||||
SQInteger kw, kh;
|
||||
sq_getinteger(vm, -5, &kw);
|
||||
sq_getinteger(vm, -4, &kh);
|
||||
|
||||
int kernel[1024];
|
||||
if ((kw * kh) > 1024)
|
||||
return sq_throwerror(vm, "The convolution kernel is exceeding 1024 entries.");
|
||||
|
||||
sq_pushnull(vm); // iterator
|
||||
for (int n = 0; n < (kw * kh); ++n)
|
||||
{
|
||||
if (SQ_FAILED(sq_next(vm, -4)))
|
||||
break;
|
||||
|
||||
// Here -1 is the value and -2 is the key.
|
||||
SQInteger v;
|
||||
sq_getinteger(vm, -1, &v);
|
||||
kernel[n] = v;
|
||||
sq_pop(vm, 2); // Pops key and val before the next iteration.
|
||||
}
|
||||
sq_pop(vm, 1); // Pop the iterator.
|
||||
|
||||
SQFloat weight;
|
||||
sq_getfloat(vm, -2, &weight);
|
||||
SQInteger pass;
|
||||
sq_getinteger(vm, -1, &pass);
|
||||
|
||||
sq_pop(vm, 4); // Pop function arguments.
|
||||
|
||||
if (!pic->ApplyConvolution(kw, kh, kernel, int(weight * 256), pass))
|
||||
return sq_throwerror(vm, "Convolution filter failed.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
SQInteger PictureLine(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(6)
|
||||
__SQ_GETSAFEPTR(pic, Picture, typetag_Picture)
|
||||
__SQ_GETFLOAT(sx)
|
||||
__SQ_GETFLOAT(sy)
|
||||
__SQ_GETFLOAT(ex)
|
||||
__SQ_GETFLOAT(ey)
|
||||
__SQ_GETVECTORW(c)
|
||||
__SQ_GETEND
|
||||
|
||||
fRect rect = pic->GetRect().AsFloat();
|
||||
rect.ex -= 2; rect.ey -= 2;
|
||||
if ((rect.ex <= rect.sx) || (rect.ey < rect.sy))
|
||||
return 0;
|
||||
pic->DrawLineHQ(sx, sy, ex, ey, c.x, c.y, c.z, c.w, &rect);
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PictureLoadContent(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(pic, Picture, typetag_Picture)
|
||||
__SQ_GETSTRING(path)
|
||||
bool r = PictureIO::Get().Load(*pic, path);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(r)
|
||||
}
|
||||
SQInteger PictureSaveTGA(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(p, Picture, typetag_Picture)
|
||||
__SQ_GETSTRING(path)
|
||||
if (!PictureIO::Get().TgaSave(*p, path))
|
||||
return sq_throwerror(vm, String::Format("Failed to save picture to '%s'", path));
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PictureSaveJPG(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(p, Picture, typetag_Picture)
|
||||
__SQ_GETSTRING(path)
|
||||
p->Convert(PixelFormat::RGB8);
|
||||
if (!PictureIO::Get().Save(*p, path, "IJG"))
|
||||
return sq_throwerror(vm, String::Format("Failed to save picture to '%s'", path));
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PictureGetRect(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(p, Picture, typetag_Picture)
|
||||
iRect rect(0, 0, 0, 0);
|
||||
if (p) rect.Set(0, 0, p->GetWidth(), p->GetHeight());
|
||||
__SQ_RETURNRECT(rect)
|
||||
}
|
||||
SQInteger PictureAlloc(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(p, Picture, typetag_Picture)
|
||||
__SQ_GETINT(w)
|
||||
__SQ_GETINT(h)
|
||||
__SQ_GETEND
|
||||
if (!p->AllocAs(w, h))
|
||||
return sq_throwerror(vm, "Failed to allocate picture buffer");
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PictureResize(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(p, Picture, typetag_Picture)
|
||||
__SQ_GETINT(w)
|
||||
__SQ_GETINT(h)
|
||||
__SQ_GETEND
|
||||
p->Resize(w, h);
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PictureSetPixel(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(4)
|
||||
__SQ_GETSAFEPTR(p, Picture, typetag_Picture)
|
||||
__SQ_GETFLOAT(x)
|
||||
__SQ_GETFLOAT(y)
|
||||
__SQ_GETVECTORW(c)
|
||||
__SQ_GETEND
|
||||
p->DrawPlot(x, y, c.x, c.y, c.z, c.w);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PictureGetPixel(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(p, Picture, typetag_Picture)
|
||||
__SQ_GETFLOAT(x)
|
||||
__SQ_GETFLOAT(y)
|
||||
__SQ_GETEND
|
||||
Color c;
|
||||
p->Sample(x / p->GetWidth(), y / p->GetHeight(), c);
|
||||
__SQ_RETURNVECTORW(Vector4(c.x, c.y, c.z, c.w))
|
||||
}
|
||||
SQInteger PictureFlip(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(p, Picture, typetag_Picture)
|
||||
__SQ_GETBOOL(h)
|
||||
__SQ_GETBOOL(v)
|
||||
__SQ_GETEND
|
||||
p->Flip(asbool(h), asbool(v));
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PictureFillLockAlpha(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(p, Picture, typetag_Picture)
|
||||
__SQ_GETVECTORW(c)
|
||||
__SQ_GETEND
|
||||
p->Fill(c.x, c.y, c.z, c.w, 0, true);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PictureFill(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(p, Picture, typetag_Picture)
|
||||
__SQ_GETVECTORW(c)
|
||||
__SQ_GETEND
|
||||
p->Fill(c.x, c.y, c.z, c.w);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PictureFillRect(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(p, Picture, typetag_Picture)
|
||||
__SQ_GETVECTORW(c)
|
||||
__SQ_GETRECT(clip_rect)
|
||||
__SQ_GETEND
|
||||
p->Fill(c.x, c.y, c.z, c.w, &clip_rect);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PictureBlitRect(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(5)
|
||||
__SQ_GETSAFEPTR(src, Picture, typetag_Picture)
|
||||
__SQ_GETSAFEPTR(dst, Picture, typetag_Picture)
|
||||
__SQ_GETRECT(src_rect)
|
||||
__SQ_GETRECT(dst_rect)
|
||||
__SQ_GETINT(blend_mode)
|
||||
__SQ_GETEND
|
||||
Picture::Blit(*src, *dst, &src_rect, &dst_rect, (Picture::BlendMode)blend_mode);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PictureBlitRectMasked(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(5)
|
||||
__SQ_GETSAFEPTR(src, Picture, typetag_Picture)
|
||||
__SQ_GETSAFEPTR(dst, Picture, typetag_Picture)
|
||||
__SQ_GETSAFEPTR(msk, Picture, typetag_Picture)
|
||||
__SQ_GETRECT(src_rect)
|
||||
__SQ_GETRECT(dst_rect)
|
||||
__SQ_GETEND
|
||||
Picture::BlitMask(*src, *dst, *msk, &src_rect, &dst_rect);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PictureBlit(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(src, Picture, typetag_Picture)
|
||||
__SQ_GETSAFEPTR(dst, Picture, typetag_Picture)
|
||||
__SQ_GETINT(blend_mode)
|
||||
__SQ_GETEND
|
||||
Picture::Blit(*src, *dst, 0, 0, (Picture::BlendMode)blend_mode);
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------
|
||||
void RegisterPictureBinding(HSQUIRRELVM vm)
|
||||
//--------------------------------------------------------
|
||||
{
|
||||
/*#
|
||||
Topic: Picture
|
||||
Type: Picture
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: PictureManagement
|
||||
Desc: Management
|
||||
#*/
|
||||
/*#
|
||||
Func: NewPicture
|
||||
Proto: Picture:int width,int height
|
||||
Desc: Create a new picture, width and height are specified in pixels.
|
||||
Example: local picture = NewPicture()
|
||||
#*/
|
||||
sq_register(vm, NewPicture, "NewPicture", _SC(".nn"));
|
||||
/*#
|
||||
Func: LoadPicture
|
||||
Proto: Picture:string path
|
||||
Desc: Load a picture. This function supports the following formats: Jpeg, Bmp, Targa, Png, Gif and PSD with alpha channel.
|
||||
Note: No caching mechanism involved, every call to this function will result in a filesystem access.
|
||||
Example: local picture = LoadPicture("assets/picture.png")
|
||||
#*/
|
||||
sq_register(vm, LoadPicture, "LoadPicture", _SC(".s"));
|
||||
/*#
|
||||
Func: PictureClone
|
||||
Proto: Picture:Picture source
|
||||
Desc: Clone a picture, return the cloned picture.
|
||||
#*/
|
||||
sq_register(vm, PictureClone, "PictureClone", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: PictureDrawing
|
||||
Desc: Drawing
|
||||
#*/
|
||||
/*#
|
||||
Func: PictureAlloc
|
||||
Proto: bool:Picture,width,height
|
||||
Desc: Change the picture internal storage dimensions, existing data will be lost.
|
||||
#*/
|
||||
sq_register(vm, PictureAlloc, "PictureAlloc", _SC(".xnn"));
|
||||
/*#
|
||||
Func: PictureLoadContent
|
||||
Proto: bool:Picture,string path
|
||||
Desc: Reload a picture object content from file.
|
||||
See: LoadPicture
|
||||
#*/
|
||||
sq_register(vm, PictureLoadContent, "PictureLoadContent", _SC(".xs"));
|
||||
/*#
|
||||
Func: PictureSaveTGA
|
||||
Proto: void:Picture,string path
|
||||
Desc: Save a picture object to Targa.
|
||||
Note: Make sure that you have access to the filesystem you plan on writing to.
|
||||
See: SystemHasMountPoint
|
||||
#*/
|
||||
sq_register(vm, PictureSaveTGA, "PictureSaveTGA", _SC(".xs"));
|
||||
/*#
|
||||
Func: PictureSaveJPG
|
||||
Proto: void:Picture,string path
|
||||
Desc: Save a picture object to jpg.
|
||||
Note: Make sure that you have access to the filesystem you plan on writing to.
|
||||
See: SystemHasMountPoint
|
||||
#*/
|
||||
sq_register(vm, PictureSaveJPG, "PictureSaveJPG", _SC(".xs"));
|
||||
/*#
|
||||
Func: PictureGetRect
|
||||
Proto: Rect:Picture
|
||||
Desc: Return a picture bounding rectangle.
|
||||
Example:
|
||||
local pict = PictureLoad("picture.psd")
|
||||
local rect = PictureGetRect(pict)
|
||||
|
||||
print("Picture width = " + rect.GetWidth() + ", height = " + rect.GetHeight())
|
||||
#*/
|
||||
sq_register(vm, PictureGetRect, "PictureGetRect", _SC(".x"));
|
||||
/*#
|
||||
Func: PictureFill
|
||||
Proto: void:Picture,Vector rgba
|
||||
Desc: Fill a picture with a solid color defined as an RGBA vector.
|
||||
#*/
|
||||
sq_register(vm, PictureFill, "PictureFill", _SC(".xx"));
|
||||
/*#
|
||||
Func: PictureFillLockAlpha
|
||||
Proto: void:Picture,Vector rgba
|
||||
Desc: Fill a picture with a solid color defined from an RGBA vector, does not write to alpha.
|
||||
#*/
|
||||
sq_register(vm, PictureFillLockAlpha, "PictureFillLockAlpha", _SC(".xx"));
|
||||
/*#
|
||||
Func: PictureFillRect
|
||||
Proto: void:Picture,Vector rgba,Rect
|
||||
Desc: Fill a rectangle inside a picture with a solid color defined from an RGBA vector.
|
||||
#*/
|
||||
sq_register(vm, PictureFillRect, "PictureFillRect", _SC(".xxx"));
|
||||
/*#
|
||||
Func: PictureApplyConvolution
|
||||
Proto: void:Picture,int kernel_width,int kernel_height,array kernel_values,float filter_weight,int pass_count
|
||||
Desc: Apply a convolution filter to the picture using a user specified kernel of values.<br>
|
||||
<br>
|
||||
The <em>weight</em> and <em>pass</em> parameters will be 1 in most use case,
|
||||
kernel values are integer in the nominal range [0;255].
|
||||
Example:
|
||||
function BlurPicture(picture, blur_strength = 1, blur_pass_count = 1)
|
||||
{
|
||||
local kernel = // 7x7 kernel
|
||||
[
|
||||
0, 1, 2, 4, 2, 1, 0,
|
||||
1, 2, 4, 6, 4, 2, 1,
|
||||
2, 3, 5, 8, 5, 3, 2,
|
||||
2, 4, 8, 8, 8, 4, 2,
|
||||
2, 3, 5, 8, 5, 3, 2,
|
||||
1, 2, 4, 6, 4, 2, 1,
|
||||
0, 1, 2, 4, 2, 1, 0
|
||||
]
|
||||
PictureApplyConvolution(picture, 7, 7, kernel, blur_strength, blur_pass_count)
|
||||
}
|
||||
#*/
|
||||
sq_register(vm, PictureApplyConvolution, "PictureApplyConvolution", _SC(".xiiani"));
|
||||
/*#
|
||||
Func: PictureLine
|
||||
Proto: bool:Texture,float start_x,float start_y,float end_x,float end_y,Vector rgba
|
||||
Desc: Draw a line, color is specified as an RGBA vector.
|
||||
#*/
|
||||
sq_register(vm, PictureLine, "PictureLine", _SC(".xnnnnx"));
|
||||
/*#
|
||||
Func: PictureWriteFont
|
||||
Proto: void:Picture,rect,string text,Font font,TextState
|
||||
Desc: Render formatted text to a picture.<br>
|
||||
TextState is table containing the following keys:<br>
|
||||
<ul>
|
||||
<li><b>'size'</b>: Size in pixels.
|
||||
<li><b>'color'</b>: Hexadecimal RGBA (eg. 0xff0000ff for red at 100% opacity).
|
||||
<li><b>'align'</b>: Text alignment, can be any of "left", "center", "right" or "justify".
|
||||
<li><b>'format'</b>: Text formating, can be any of "standard", "paragraph" or "column".
|
||||
<li><b>'tracking'</b>: Integer value specifying an extra space between glyphs.
|
||||
<li><b>'heading'</b>: Integer value specifying an extra space between lines.
|
||||
</ul>
|
||||
#*/
|
||||
sq_register(vm, PictureWriteText, "PictureWriteFont", _SC(".xxsxt"));
|
||||
sq_register(vm, PictureWriteText, "PictureWriteText", _SC(".xxsxt"));
|
||||
/*#
|
||||
Func: PictureSetPixel
|
||||
Proto: void:Picture,float x,float y,Vector rgba
|
||||
Desc: Set picture pixel at coordinate {x, y} in picture space from an RGBA vector.
|
||||
#*/
|
||||
sq_register(vm, PictureSetPixel, "PictureSetPixel", _SC(".xnnx"));
|
||||
/*#
|
||||
Func: PictureGetPixel
|
||||
Proto: Vector:Picture,float x,float y
|
||||
Desc: Return the picture pixel at coordinate {x, y} in picture space as an RGBA vector.
|
||||
#*/
|
||||
sq_register(vm, PictureGetPixel, "PictureGetPixel", _SC(".xnn"));
|
||||
|
||||
/*#
|
||||
Section: PictureManipulation
|
||||
Desc: Manipulation
|
||||
#*/
|
||||
/*#
|
||||
Func: PictureResize
|
||||
Proto: void:Picture,float w,float h
|
||||
Desc: Resize picture.
|
||||
#*/
|
||||
sq_register(vm, PictureResize, "PictureResize", _SC(".xii"));
|
||||
/*#
|
||||
Func: PictureFlip
|
||||
Proto: void:Picture,bool horizontal, bool vertical
|
||||
Desc: Flip picture on one or both axis.
|
||||
#*/
|
||||
sq_register(vm, PictureFlip, "PictureFlip", _SC(".xbb"));
|
||||
|
||||
/*#
|
||||
Section: PictureBlitting
|
||||
Desc: Blitting
|
||||
#*/
|
||||
/*#
|
||||
Func: PictureBlit
|
||||
Proto: void:Picture source,Picture destination,BlendMode mode
|
||||
Desc: Blit a picture to another picture with a selectable blend mode.
|
||||
#*/
|
||||
sq_register(vm, PictureBlit, "PictureBlit", _SC(".xxi"));
|
||||
/*#
|
||||
Func: PictureBlitRect
|
||||
Proto: void:Picture source,Picture destination,Rect source,Rect destination,BlendMode mode
|
||||
Desc: Blit a picture to another picture, both clipping zones and the blend mode can be specified.
|
||||
#*/
|
||||
sq_register(vm, PictureBlitRect, "PictureBlitRect", _SC(".xxxxi"));
|
||||
/*#
|
||||
Func: PictureBlitRectMasked
|
||||
Proto: void:Picture source,Picture destination,Picture mask,Rect source,Rect destination
|
||||
Desc: Blit a picture to another picture using a third picture alpha channel as an opacity mask.
|
||||
#*/
|
||||
sq_register(vm, PictureBlitRectMasked, "PictureBlitRectMasked", _SC(".xxxxx"));
|
||||
|
||||
sq_pushroottable(vm);
|
||||
|
||||
/*#
|
||||
Enum: BlendMode
|
||||
Values: BlendReplace,BlendAdd,BlendCompose,BlendComposeFast,BlendMultiply,BlendMultiply2x,BlendAlphaAdd,BlendAlphaMultiply,BlendAlphaMultiply2x,RgbToAlpha
|
||||
#*/
|
||||
sq_pushstring(vm, "BlendReplace", -1); sq_pushinteger(vm, Picture::BlendReplace); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "BlendAdd", -1); sq_pushinteger(vm, Picture::BlendAdd); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "BlendCompose", -1); sq_pushinteger(vm, Picture::BlendCompose); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "BlendComposeFast", -1); sq_pushinteger(vm, Picture::BlendComposeFast); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "BlendMultiply", -1); sq_pushinteger(vm, Picture::BlendMultiply); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "BlendMultiply2x", -1); sq_pushinteger(vm, Picture::BlendMultiply2x); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "BlendAlphaAdd", -1); sq_pushinteger(vm, Picture::BlendAlphaAdd); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "BlendAlphaMultiply", -1); sq_pushinteger(vm, Picture::BlendAlphaMultiply); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "BlendAlphaMultiply2x", -1); sq_pushinteger(vm, Picture::BlendAlphaMultiply2x); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "RgbToAlpha", -1); sq_pushinteger(vm, Picture::RgbToAlpha); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
262
include/modules/script_squirrel/legacy/platform_binding.cpp
Normal file
262
include/modules/script_squirrel/legacy/platform_binding.cpp
Normal file
@ -0,0 +1,262 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
nEngine - GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "squirrel.h"
|
||||
#include "script_squirrel/legacy/binding_helpers.h"
|
||||
#include "licensing/licensing.h"
|
||||
#include "analytics/analytics.h"
|
||||
#include "billing/billing.h"
|
||||
#include "locale/country.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PlatformAnalyticsLogEvent(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(name)
|
||||
if (Platform::Get().analytics.IsValid())
|
||||
Platform::Get().analytics->logEvent(name);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PlatformAnalyticsServeFullscreenAd(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(location)
|
||||
if (Platform::Get().analytics.IsValid())
|
||||
Platform::Get().analytics->serveFullscreenAd(location);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PlatformBillingConfirmEvent(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(id)
|
||||
if (Platform::Get().billing.IsNull())
|
||||
return sq_throwerror(vm, "No billing system on this platform.");
|
||||
Platform::Get().billing->confirmPurchase(id);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PlatformBillingRestorePurchases(HSQUIRRELVM vm)
|
||||
{
|
||||
if (Platform::Get().billing.IsNull())
|
||||
return sq_throwerror(vm, "No billing system on this platform.");
|
||||
Platform::Get().billing->restorePurchases();
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PlatformBillingRequestPurchase(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(id)
|
||||
if (Platform::Get().billing.IsNull())
|
||||
return sq_throwerror(vm, "No billing system on this platform.");
|
||||
Platform::Get().billing->requestPurchase(id);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger PlatformBillingIsSupported(HSQUIRRELVM vm)
|
||||
{ __SQ_RETURNBOOL(Platform::Get().billing.IsValid()) }
|
||||
SQInteger PlatformGetLocale(HSQUIRRELVM vm)
|
||||
{ __SQ_RETURNSTRING(Platform::Get().GetLocale()) }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PlatformLicensingIsSupported(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_RETURNBOOL(Platform::Get().licensing.IsValid())
|
||||
}
|
||||
SQInteger PlatformLicensingCheck(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(id)
|
||||
if (Platform::Get().licensing.IsNull())
|
||||
return sq_throwerror(vm, "No licensing system on this platform.");
|
||||
Platform::Get().licensing->updateLicence(id);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(true)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PlatformGetName(HSQUIRRELVM vm)
|
||||
{ __SQ_RETURNSTRING(Platform::Get().GetName()) }
|
||||
SQInteger PlatformGetDeviceName(HSQUIRRELVM vm)
|
||||
{ __SQ_RETURNSTRING(Platform::Get().GetDeviceName()) }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PlatformOpenURL(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(url)
|
||||
bool r = Platform::Get().OpenURL(url);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(r)
|
||||
}
|
||||
SQInteger PlatformSendToBackground(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETBOOL(kill)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(Platform::Get().SendToBackground(asbool(kill)))
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PlatformGetUserPath(HSQUIRRELVM vm)
|
||||
{
|
||||
String path;
|
||||
if (!Platform::Get().GetUserDir(path))
|
||||
return sq_throwerror(vm, "Failed to get user path.");
|
||||
__SQ_RETURNSTRING(path)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger PlatformOpenAppPage(HSQUIRRELVM vm)
|
||||
{
|
||||
Platform::Get().OpenAppPage();
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterPlatformBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
using namespace GS::Script;
|
||||
|
||||
/*#
|
||||
Section: SystemMisc
|
||||
Desc: Miscellaneous
|
||||
#*/
|
||||
/*#
|
||||
Func: PlatformOpenURL
|
||||
Proto: bool:String id
|
||||
Desc: Open an URL using the platform browser if available.
|
||||
#*/
|
||||
sq_register(vm, PlatformOpenURL, "PlatformOpenURL", _SC(".s"));
|
||||
/*#
|
||||
Func: PlatformSendToBackground
|
||||
Proto: bool:bool kill
|
||||
Desc: Send the current application to background, optionally try to kill it.
|
||||
#*/
|
||||
sq_register(vm, PlatformSendToBackground, "PlatformSendToBackground", _SC(".b"));
|
||||
|
||||
/*#
|
||||
Func: PlatformGetUserPath
|
||||
Proto: String:
|
||||
Desc: Return the current user path.
|
||||
#*/
|
||||
sq_register(vm, PlatformGetUserPath, "PlatformGetUserPath", _SC("."));
|
||||
|
||||
/*#
|
||||
Section: SystemVisibility
|
||||
Desc: Platform visibility
|
||||
#*/
|
||||
/*#
|
||||
Func: PlatformOpenAppPage
|
||||
Proto: void:
|
||||
Desc: Open the platform specific application page, use this to send the user to your rating page.
|
||||
#*/
|
||||
sq_register(vm, PlatformOpenAppPage, "PlatformOpenAppPage", _SC("."));
|
||||
|
||||
/*#
|
||||
Section: SystemLicensing
|
||||
Desc: Licensing
|
||||
#*/
|
||||
/*#
|
||||
Func: PlatformLicensingCheck
|
||||
Proto: void:String license_info
|
||||
Desc: Launch an asynchronous licensing request, the result will be sent to your script global 'OnLicensingEvent(String event)' function.
|
||||
#*/
|
||||
sq_register(vm, PlatformLicensingCheck, "PlatformLicensingCheck", _SC(".s"));
|
||||
/*#
|
||||
Func: PlatformLicensingIsSupported
|
||||
Proto: bool:
|
||||
Desc: Returns true if the current platform supports app license verification.
|
||||
#*/
|
||||
sq_register(vm, PlatformLicensingIsSupported, "PlatformLicensingIsSupported", _SC("."));
|
||||
|
||||
/*#
|
||||
Section: SystemBilling
|
||||
Desc: In-app billing
|
||||
#*/
|
||||
/*#
|
||||
Func: PlatformBillingConfirmEvent
|
||||
Proto: void:String id
|
||||
Desc: Confirm a billing event (like a purchase or a refund).
|
||||
#*/
|
||||
sq_register(vm, PlatformBillingConfirmEvent, "PlatformBillingConfirmEvent", _SC(".s"));
|
||||
/*#
|
||||
Func: PlatformBillingRestorePurchases
|
||||
Proto: void:
|
||||
Desc: Restore all managed purchases. The billing event callback will be called for each purchase ever made by the current user with the event string "Restored".
|
||||
#*/
|
||||
sq_register(vm, PlatformBillingRestorePurchases, "PlatformBillingRestorePurchases", _SC("."));
|
||||
/*#
|
||||
Func: PlatformBillingRequestPurchase
|
||||
Proto: void:String id
|
||||
Desc: Launch a purchase intent for the specified virtual good identifier. Returns true of the intent was successfully launched. Results will be transmitted to you through the global 'OnBillingEvent(String event, String item)' script callback.
|
||||
#*/
|
||||
sq_register(vm, PlatformBillingRequestPurchase, "PlatformBillingRequestPurchase", _SC(".s"));
|
||||
/*#
|
||||
Func: PlatformBillingIsSupported
|
||||
Proto: bool:
|
||||
Desc: Returns true if the current platform supports in-app billing (in-app purchase).
|
||||
#*/
|
||||
sq_register(vm, PlatformBillingIsSupported, "PlatformBillingIsSupported", _SC("."));
|
||||
/*#
|
||||
Func: PlatformGetLocale
|
||||
Proto: String:
|
||||
Desc: Return the current platform locale ISO2 code string (ISO 3166 two-character alphabetic code).
|
||||
#*/
|
||||
sq_register(vm, PlatformGetLocale, "PlatformGetLocale", _SC("."));
|
||||
|
||||
/*#
|
||||
Section: SystemAnalytics
|
||||
Desc: Analytics
|
||||
#*/
|
||||
/*#
|
||||
Func: PlatformAnalyticsLogEvent
|
||||
Proto: void:String name
|
||||
Desc: Log a named analytics event.
|
||||
#*/
|
||||
sq_register(vm, PlatformAnalyticsLogEvent, "PlatformAnalyticsLogEvent", _SC(".s"));
|
||||
/*#
|
||||
Func: PlatformAnalyticsServeFullscreenAd
|
||||
Proto: void:String location
|
||||
Desc: Serve a fullscreen ad, the location string is used as a marker to track the location of the display.
|
||||
#*/
|
||||
sq_register(vm, PlatformAnalyticsServeFullscreenAd, "PlatformAnalyticsServeFullscreenAd", _SC(".s"));
|
||||
|
||||
/*#
|
||||
Section: SystemHardware
|
||||
Desc: Host device
|
||||
#*/
|
||||
/*#
|
||||
Func: PlatformGetName
|
||||
Proto: String:
|
||||
Desc: Return the platform name (eg. "Win32", "iOS", "Android", ...).
|
||||
Note: A platform may run on several devices.
|
||||
fd See: PlatformGetDeviceName
|
||||
#*/
|
||||
sq_register(vm, PlatformGetDeviceName, "PlatformGetDeviceName", _SC("."));
|
||||
/*#
|
||||
Func: PlatformGetDeviceName
|
||||
Proto: String:
|
||||
Desc: Return the device name the platform is currently running on (eg. "iPad", "iPhone").
|
||||
#*/
|
||||
sq_register(vm, PlatformGetDeviceName, "PlatformGetDeviceName", _SC("."));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
241
include/modules/script_squirrel/legacy/profiler_binding.cpp
Normal file
241
include/modules/script_squirrel/legacy/profiler_binding.cpp
Normal file
@ -0,0 +1,241 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
2023 Emmanuel Julien
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
#include "binding_helpers.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct CallId {
|
||||
SQUserPointer caller; // caller funcid, 0 means native call
|
||||
SQUserPointer funcid;
|
||||
};
|
||||
|
||||
typedef uint64_t time_ns;
|
||||
|
||||
static time_ns get_clock() {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
typedef uint32_t CallIdx;
|
||||
|
||||
struct Call {
|
||||
CallId id;
|
||||
time_ns start;
|
||||
time_ns total{0};
|
||||
uint32_t hit{0}; // number of time this call was performed
|
||||
std::vector<CallIdx> child_calls; // [EJ] this is wasteful and inefficient
|
||||
};
|
||||
|
||||
struct FuncInfo {
|
||||
std::string name;
|
||||
std::string source;
|
||||
};
|
||||
|
||||
struct VMProfile {
|
||||
std::map<SQUserPointer, FuncInfo> func_info;
|
||||
|
||||
std::vector<Call> all_calls;
|
||||
CallIdx call_count{0};
|
||||
|
||||
std::vector<CallIdx> root_calls;
|
||||
std::vector<CallIdx> callstack; // current callstack
|
||||
};
|
||||
|
||||
static std::map<HSQUIRRELVM, VMProfile> vm_profiles;
|
||||
|
||||
static CallIdx find_call(std::vector<Call> &all_calls, std::vector<CallIdx> &calls, CallId call_id) {
|
||||
for (CallIdx i : calls) {
|
||||
const Call &call = all_calls[i];
|
||||
if (call.id.caller == call_id.caller && call.id.funcid == call_id.funcid) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct CallProfile {
|
||||
uint32_t hit; // number of calls
|
||||
time_ns total; // duration of all calls
|
||||
time_ns child; // duration of all child calls
|
||||
};
|
||||
|
||||
static CallProfile get_call_profile(const std::vector<Call> &all_calls, const Call &call) {
|
||||
CallProfile profile;
|
||||
profile.hit = call.hit;
|
||||
profile.total = call.total;
|
||||
profile.child = 0;
|
||||
|
||||
for (const CallIdx i : call.child_calls) {
|
||||
profile.child += all_calls[i].total;
|
||||
}
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
static CallProfile get_calls_profile(const std::vector<Call> &all_calls, const std::vector<CallIdx> &idxs) {
|
||||
CallProfile profile;
|
||||
profile.hit = 0;
|
||||
profile.total = 0;
|
||||
profile.child = 0;
|
||||
|
||||
for (const auto idx : idxs) {
|
||||
const CallProfile call_profile = get_call_profile(all_calls, all_calls[idx]);
|
||||
profile.hit += call_profile.hit;
|
||||
profile.total += call_profile.total;
|
||||
profile.child += call_profile.child;
|
||||
}
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
static void native_hook(HSQUIRRELVM vm, SQInteger event_type, const SQChar *sourcename, SQInteger line, const SQChar *funcname) {
|
||||
VMProfile &profile = vm_profiles[vm];
|
||||
|
||||
const time_ns time = get_clock();
|
||||
|
||||
if (event_type == 'l') { // line execution
|
||||
// TODO reimplement if ever needed
|
||||
} else if (event_type == 'c') { // function call
|
||||
SQFunctionInfo fi;
|
||||
sq_getfunctioninfo(vm, 0, &fi);
|
||||
|
||||
if (profile.func_info.find(fi.funcid) == std::end(profile.func_info)) {
|
||||
FuncInfo &info = profile.func_info[fi.funcid];
|
||||
info.name = fi.name;
|
||||
info.source = fi.source;
|
||||
}
|
||||
|
||||
//
|
||||
CallId call_id = {nullptr, fi.funcid};
|
||||
|
||||
std::vector<CallIdx> *child_calls = &profile.root_calls;
|
||||
|
||||
if (!profile.callstack.empty()) {
|
||||
Call &call = profile.all_calls[profile.callstack.back()];
|
||||
|
||||
call_id.caller = call.id.funcid;
|
||||
child_calls = &call.child_calls;
|
||||
}
|
||||
|
||||
//
|
||||
CallIdx i = find_call(profile.all_calls, *child_calls, call_id);
|
||||
|
||||
if (i == 0) {
|
||||
i = ++profile.call_count;
|
||||
child_calls->push_back(i);
|
||||
|
||||
profile.all_calls.resize(profile.call_count + 1); // allocate call object
|
||||
}
|
||||
|
||||
Call &call = profile.all_calls[i];
|
||||
call.id = call_id;
|
||||
call.start = time;
|
||||
++call.hit;
|
||||
|
||||
profile.callstack.push_back(i);
|
||||
} else if (event_type == 'r') { // returning from a function
|
||||
if (!profile.callstack.empty()) {
|
||||
Call &call = profile.all_calls[profile.callstack.back()];
|
||||
|
||||
const time_ns duration = time - call.start;
|
||||
call.total += duration;
|
||||
|
||||
profile.callstack.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
bool save_profile(HSQUIRRELVM vm, const char *path) {
|
||||
const auto i = vm_profiles.find(vm);
|
||||
|
||||
if (i == std::end(vm_profiles)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const VMProfile &profile = i->second;
|
||||
|
||||
// build a set of all functions (source + name) called during the profile
|
||||
// note: funcid is not unique in GS, probably because all scripts use a custom context in which the script is reloaded
|
||||
std::set<std::string> ids;
|
||||
|
||||
for (const auto &i : profile.func_info) {
|
||||
ids.insert(i.second.source + ":" + i.second.name);
|
||||
}
|
||||
|
||||
// compute timings for each function
|
||||
std::map<std::string, CallProfile> func_profiles;
|
||||
|
||||
for (const auto &id : ids) {
|
||||
std::vector<CallIdx> idxs;
|
||||
|
||||
for (size_t i = 1; i < profile.all_calls.size(); ++i) {
|
||||
const Call &call = profile.all_calls[i];
|
||||
|
||||
const FuncInfo &info = profile.func_info.find(call.id.funcid)->second;
|
||||
if (id == info.source + ":" + info.name) {
|
||||
idxs.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
func_profiles[id] = get_calls_profile(profile.all_calls, idxs);
|
||||
}
|
||||
|
||||
// output to CSV
|
||||
std::ofstream csv(path);
|
||||
csv << "function,total,children,self,hit,ntotal,nself" << std::endl;
|
||||
|
||||
for (const auto &i : func_profiles) {
|
||||
csv << i.first << ",";
|
||||
|
||||
const CallProfile &call_profile = i.second;
|
||||
|
||||
const time_ns self = call_profile.total - call_profile.child;
|
||||
|
||||
csv << call_profile.total << ",";
|
||||
csv << call_profile.child << ",";
|
||||
csv << self << ",";
|
||||
csv << call_profile.hit << ",";
|
||||
csv << call_profile.total / call_profile.hit << ",";
|
||||
csv << self / call_profile.hit;
|
||||
|
||||
csv << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
SQInteger StartProfiler(HSQUIRRELVM vm) {
|
||||
sq_setnativedebughook(vm, native_hook);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SQInteger SaveProfile(HSQUIRRELVM vm) {
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(path)
|
||||
const bool res = save_profile(vm, path);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(res)
|
||||
}
|
||||
|
||||
SQInteger StopProfiler(HSQUIRRELVM vm) {
|
||||
sq_setnativedebughook(vm, nullptr);
|
||||
vm_profiles.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
void RegisterProfilerBinding(HSQUIRRELVM vm) {
|
||||
GS::Script::sq_register(vm, StartProfiler, "StartProfiler", _SC("."));
|
||||
GS::Script::sq_register(vm, SaveProfile, "SaveProfile", _SC(".s"));
|
||||
GS::Script::sq_register(vm, StopProfiler, "StopProfiler", _SC("."));
|
||||
}
|
||||
493
include/modules/script_squirrel/legacy/project_binding.cpp
Normal file
493
include/modules/script_squirrel/legacy/project_binding.cpp
Normal file
@ -0,0 +1,493 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "script_squirrel/legacy/binding_helpers.h"
|
||||
#include "project/project.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "ui/ui_camera.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ProjectGetClock(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_RETURNSAFEPTR(project->clock.c_ptr(), typetag_Clock)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ProjectSetAll2DLayerOffset(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_GETFLOAT(x)
|
||||
__SQ_GETFLOAT(y)
|
||||
__SQ_GETEND
|
||||
|
||||
ListForeachPtr(ProjectLayer *, layer, project->layer_list)
|
||||
if (layer->inst)
|
||||
if (S2D::Scene *scene = layer->inst->instance_2d)
|
||||
{
|
||||
scene->offset_matrix = Matrix3::IdentityMatrix();
|
||||
scene->offset_matrix.m[0][2] = x / scene->GetCurrentCamera()->resolution.x;
|
||||
scene->offset_matrix.m[1][2] = y / scene->GetCurrentCamera()->resolution.y;
|
||||
}
|
||||
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ProjectLayerGetScene(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(layer, ProjectLayer, typetag_ProjectLayer)
|
||||
if (!layer->inst)
|
||||
return sq_throwerror(vm, "No scene in project layer");
|
||||
__SQ_RETURNSAFEPTR(layer->inst, typetag_ProjectScene)
|
||||
}
|
||||
SQInteger ProjectLayerSetZOrder(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(layer, ProjectLayer, typetag_ProjectLayer)
|
||||
__SQ_GETFLOAT(zorder)
|
||||
__SQ_GETEND
|
||||
layer->zorder = zorder;
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ProjectLayerGetZOrder(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(layer, ProjectLayer, typetag_ProjectLayer)
|
||||
__SQ_RETURNFLOAT(layer->zorder)
|
||||
}
|
||||
SQInteger ProjectAddLayer(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_GETSAFEPTR(instance, ProjectSceneInstance, typetag_ProjectScene)
|
||||
__SQ_GETFLOAT(zorder)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(project->AddLayer(instance, zorder), typetag_ProjectLayer)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ProjectNewScene3D(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_RETURNMANAGEDSAFEPTR(project->Instantiate(new S3D::Scene(project->vm)), typetag_ProjectScene)
|
||||
}
|
||||
SQInteger ProjectNewScene2D(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_RETURNMANAGEDSAFEPTR(project->Instantiate(new S2D::Scene(project->vm)), typetag_ProjectScene)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ProjectGetSceneLayerList(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_GETSAFEPTR(scene, ProjectSceneInstance, typetag_ProjectScene)
|
||||
__SQ_GETEND
|
||||
|
||||
sq_newarray(vm, 0);
|
||||
for (uint n = 0; n < project->layer_list.GetCount(); ++n)
|
||||
{
|
||||
ProjectLayer *layer = project->layer_list[n];
|
||||
if (layer->inst == scene)
|
||||
{
|
||||
CObject::Push(vm, (void *)layer, typetag_ProjectLayer);
|
||||
sq_arrayappend(vm, -2);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
SQInteger ProjectInstantiateScene(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_GETSTRING(path)
|
||||
sq_collectgarbage(vm);
|
||||
ProjectSceneInstance *project_scene = project->Instantiate(path);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(project_scene, typetag_ProjectScene)
|
||||
}
|
||||
SQInteger ProjectSceneIsActive(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_GETSAFEPTR(scene, ProjectSceneInstance, typetag_ProjectScene)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(project && scene ? project->IsActive(*scene) : false)
|
||||
}
|
||||
SQInteger ProjectSceneActivate(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_GETSAFEPTR(scene, ProjectSceneInstance, typetag_ProjectScene)
|
||||
__SQ_GETBOOL(active)
|
||||
__SQ_GETEND
|
||||
project->Activate(*scene, active ? true : false);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ProjectUnloadScene(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_GETSAFEPTR(scene, ProjectSceneInstance, typetag_ProjectScene)
|
||||
__SQ_GETEND
|
||||
project->Delete(scene);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ProjectFindScene(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_GETSTRING(path)
|
||||
ProjectSceneInstance *inst = project->FindSceneInstance(path);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(inst, typetag_ProjectScene)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ProjectSceneGetType(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(scene, ProjectSceneInstance, typetag_ProjectScene)
|
||||
__SQ_RETURNINT(scene->GetType())
|
||||
}
|
||||
SQInteger ProjectSceneGetInstance(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(scene, ProjectSceneInstance, typetag_ProjectScene)
|
||||
|
||||
switch (scene->GetType())
|
||||
{
|
||||
case ProjectSceneInstance::Type_Scene2d:
|
||||
__SQ_RETURNSAFEPTR(scene->instance_2d, typetag_Scene2d)
|
||||
case ProjectSceneInstance::Type_Scene3d:
|
||||
__SQ_RETURNSAFEPTR(scene->instance_3d, typetag_Scene3d)
|
||||
|
||||
default: break;
|
||||
}
|
||||
return sq_throwerror(vm, "Invalid project scene");
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ProjectGetFileName(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_RETURNSTRING(project->name.CutFilePath().toUtf8())
|
||||
}
|
||||
SQInteger ProjectGetFilePath(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_RETURNSTRING(project->name.CutFileName().toUtf8())
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ProjectSceneSetGlobal(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(scene, ProjectSceneInstance, typetag_ProjectScene)
|
||||
if (scene && (scene->GetType() == ProjectSceneInstance::Type_Scene3d))
|
||||
scene->instance_3d->SetAsScriptGlobalScene();
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ProjectGetScriptInstance(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(project, Project, typetag_Project)
|
||||
if (!project)
|
||||
return sq_suspendvm(vm);
|
||||
if (!project->script_unit->Self())
|
||||
return sq_throwerror(vm, "No script assigned to this project.");
|
||||
__SQ_RETURNOBJECT(((Script::SquirrelObject *)project->script_unit->Self())->object);
|
||||
}
|
||||
SQInteger ProjectEnd(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(project, Project, typetag_Project)
|
||||
if (project)
|
||||
project->flags.Set(Project::ProjectFlagEnd);
|
||||
// exit(0);
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ProjectLoadFont(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_GETSTRING(path)
|
||||
FontEx *font = project->font_cache->LoadFont(path);
|
||||
if (!font)
|
||||
return sq_throwerror(vm, String::Format("Failed to load font '%s'.", path));
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(font, typetag_Font)
|
||||
}
|
||||
SQInteger ProjectLoadFontAliased(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_GETSTRING(path)
|
||||
__SQ_GETSTRING(alias)
|
||||
FontEx *font = project->font_cache->LoadFont(path, alias);
|
||||
if (!font)
|
||||
return sq_throwerror(vm, String::Format("Failed to load font '%s' under alias '%s'.", path, alias));
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(font, typetag_Font)
|
||||
}
|
||||
SQInteger ProjectDeleteFontAlias(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_GETSTRING(alias)
|
||||
project->font_cache->DeleteAlias(alias);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger ProjectGetFont(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(project, Project, typetag_Project)
|
||||
__SQ_GETSTRING(path)
|
||||
FontEx *font = project->font_cache->GetAliasedFont(path);
|
||||
if (!font)
|
||||
return sq_throwerror(vm, String::Format("Font '%s' not found.", path));
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(font, typetag_Font)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterProjectBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Project
|
||||
Type: Project
|
||||
Type: ProjectLayer
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: ProjectGeneral
|
||||
Desc: General project functions
|
||||
#*/
|
||||
/*#
|
||||
Func: ProjectGetClock
|
||||
Proto: Clock:Project
|
||||
Desc: Get the project clock object.
|
||||
#*/
|
||||
sq_register(vm, ProjectGetClock, "ProjectGetClock", _SC(".x"));
|
||||
/*#
|
||||
Func: ProjectGetScriptInstance
|
||||
Proto: Instance:Project
|
||||
Desc: Get the project script instance.
|
||||
#*/
|
||||
sq_register(vm, ProjectGetScriptInstance, "ProjectGetScriptInstance", _SC(".x"));
|
||||
/*#
|
||||
Func: ProjectEnd
|
||||
Proto: void:Project
|
||||
Desc: Exit project.
|
||||
#*/
|
||||
sq_register(vm, ProjectEnd, "ProjectEnd", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: ProjectFontManagement
|
||||
Desc: UI Font management functions
|
||||
#*/
|
||||
/*#
|
||||
Func: ProjectLoadFont
|
||||
Proto: Font:Project, string path
|
||||
Desc: Load a TrueType font in the project font cache.
|
||||
#*/
|
||||
sq_register(vm, ProjectLoadFont, "ProjectLoadFont", _SC(".xs"));
|
||||
sq_register(vm, ProjectLoadFont, "ProjectLoadUIFont", _SC(".xs"));
|
||||
/*#
|
||||
Func: ProjectLoadFontAliased
|
||||
Proto: Font:Project, string path, string alias
|
||||
Desc: Load a TrueType font under a specific alias.
|
||||
#*/
|
||||
sq_register(vm, ProjectLoadFontAliased, "ProjectLoadFontAliased", _SC(".xss"));
|
||||
sq_register(vm, ProjectLoadFontAliased, "ProjectLoadUIFontAliased", _SC(".xss"));
|
||||
/*#
|
||||
Func: ProjectDeleteFontAlias
|
||||
Proto: void:Project, string alias
|
||||
Desc: Delete a font alias from the font cache.
|
||||
#*/
|
||||
sq_register(vm, ProjectDeleteFontAlias, "ProjectDeleteFontAlias", _SC(".xs"));
|
||||
sq_register(vm, ProjectDeleteFontAlias, "ProjectDeleteUIFontAlias", _SC(".xs"));
|
||||
/*#
|
||||
Func: ProjectGetFont
|
||||
Proto: Font:Project, string name
|
||||
Desc: Retrieve a font from its name.
|
||||
#*/
|
||||
sq_register(vm, ProjectGetFont, "ProjectGetFont", _SC(".xs"));
|
||||
sq_register(vm, ProjectGetFont, "ProjectGetUIFont", _SC(".xs"));
|
||||
|
||||
/*#
|
||||
Section: ProjectLayerManagement
|
||||
Desc: Layer management functions
|
||||
#*/
|
||||
/*#
|
||||
Func: ProjectLayerGetScene
|
||||
Proto: ProjectScene:ProjectLayer
|
||||
Desc: Return the scene instance a layer is displaying.
|
||||
#*/
|
||||
sq_register(vm, ProjectLayerGetScene, "ProjectLayerGetScene", _SC(".x"));
|
||||
/*#
|
||||
Func: ProjectAddLayer
|
||||
Proto: ProjectLayer:Project,ProjectScene,float zorder
|
||||
Desc: Create a new layer to display a project scene.
|
||||
Note: A scene can be added to several layers at once.
|
||||
#*/
|
||||
sq_register(vm, ProjectAddLayer, "ProjectAddLayer", _SC(".xxn"));
|
||||
/*#
|
||||
Func: ProjectLayerSetZOrder
|
||||
Proto: void:ProjectLayer,float
|
||||
Desc: Set layer Z order.
|
||||
Note: Smaller Z values are closer to the viewer.
|
||||
#*/
|
||||
sq_register(vm, ProjectLayerSetZOrder, "ProjectLayerSetZOrder", _SC(".xn"));
|
||||
/*#
|
||||
Func: ProjectLayerGetZOrder
|
||||
Proto: float:ProjectLayer
|
||||
Desc: Get layer Z order.
|
||||
#*/
|
||||
sq_register(vm, ProjectLayerGetZOrder, "ProjectLayerGetZOrder", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Func: ProjectSetAll2DLayerOffset
|
||||
Proto: void:Project,float x,float y
|
||||
Desc: Set the offset of all 2d layer in the current project stack. The offset is specified in the layer reference resolution.
|
||||
#*/
|
||||
sq_register(vm, ProjectSetAll2DLayerOffset, "ProjectSetAll2DLayerOffset", _SC(".xnn"));
|
||||
|
||||
/*#
|
||||
Section: ProjectSceneManagement
|
||||
Desc: Scene management functions
|
||||
#*/
|
||||
/*#
|
||||
Func: ProjectNewScene3D
|
||||
Proto: ProjectScene:Project
|
||||
Desc: Create a new scene 3D.
|
||||
Note: You need to add the newly created scene to a project layer to display it.
|
||||
Example:
|
||||
local project_scene = ProjectNewScene3D(g_project)
|
||||
ProjectAddLayer(g_project, project_scene, 0.5) // add the 3d scene to a project layer with Z offset of 0.5
|
||||
#*/
|
||||
sq_register(vm, ProjectNewScene3D, "ProjectNewScene", _SC(".x"));
|
||||
sq_register(vm, ProjectNewScene3D, "ProjectNewScene3D", _SC(".x"));
|
||||
/*#
|
||||
Func: ProjectNewScene2D
|
||||
Proto: ProjectScene:Project
|
||||
Desc: Create a new scene 2D.
|
||||
Note: You need to add the newly created scene to a project layer to display it.
|
||||
Example:
|
||||
local project_scene = ProjectNewScene2D(g_project)
|
||||
ProjectAddLayer(g_project, project_scene, 0.5) // add the 2d scene to a project layer with Z offset of 0.5
|
||||
#*/
|
||||
sq_register(vm, ProjectNewScene2D, "ProjectNewScene2D", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Func: ProjectFindScene
|
||||
Proto: ProjectScene:Project,string path
|
||||
Desc: Returns an instance of a specific scene in the project, returns an invalid object if no such instance could be found.
|
||||
#*/
|
||||
sq_register(vm, ProjectFindScene, "ProjectFindScene", _SC(".xs"));
|
||||
/*#
|
||||
Func: ProjectGetSceneLayerList
|
||||
Proto: Array:Project,ProjectScene
|
||||
Desc: Return all the project layers displaying a specific scene instance. A scene might be displayed by several different layers (eg. in order to display a split-screen view).
|
||||
#*/
|
||||
sq_register(vm, ProjectGetSceneLayerList, "ProjectGetSceneLayerList", _SC(".xx"));
|
||||
|
||||
/*#
|
||||
Func: ProjectSceneIsActive
|
||||
Proto: bool:Project,ProjectScene
|
||||
Desc: Return the active state of a project scene.
|
||||
#*/
|
||||
sq_register(vm, ProjectSceneIsActive, "ProjectSceneIsActive", _SC(".xx"));
|
||||
sq_register(vm, ProjectSceneIsActive, "ProjectIsSceneActive", _SC(".xx"));
|
||||
/*#
|
||||
Func: ProjectSceneActivate
|
||||
Proto: void:Project,ProjectScene,bool
|
||||
Desc: Activate or deactivate a project scene. When deactivated a scene is not updated or displayed anymore.
|
||||
#*/
|
||||
sq_register(vm, ProjectSceneActivate, "ProjectSceneActivate", _SC(".xxb"));
|
||||
sq_register(vm, ProjectSceneActivate, "ProjectActivateScene", _SC(".xxb"));
|
||||
/*#
|
||||
Func: ProjectInstantiateScene
|
||||
Proto: ProjectScene:Project,string path
|
||||
Desc: Instantiate a project scene.
|
||||
Note: You need to add the project scene to a layer to display it. This function will detect the type of scene to instantiate, 2d or 3d, from the input file.
|
||||
See: ProjectSceneGetType, ProjectDeleteScene
|
||||
Example:
|
||||
local project_scene = ProjectInstantiateScene(g_project, "scene_file.nms")
|
||||
ProjectAddLayer(g_project, project_scene, 0.5)
|
||||
#*/
|
||||
sq_register(vm, ProjectInstantiateScene, "ProjectInstantiateScene", _SC(".xs"));
|
||||
/*#
|
||||
Func: ProjectSceneSetGlobal
|
||||
Proto: void:ProjectScene
|
||||
Desc: Register scene as the global scene script object (g_scene).
|
||||
Note: The project automatically updates g_scene before updating or displaying a scene.
|
||||
#*/
|
||||
sq_register(vm, ProjectSceneSetGlobal, "ProjectSceneSetGlobal", _SC(".x"));
|
||||
/*#
|
||||
Func: ProjectDeleteScene
|
||||
Proto: void:Project,ProjectScene
|
||||
Desc: Delete a project scene.
|
||||
Note: All layers displaying this scene will be destroyed as well.
|
||||
#*/
|
||||
sq_register(vm, ProjectUnloadScene, "ProjectDeleteScene", _SC(".xx"));
|
||||
sq_register(vm, ProjectUnloadScene, "ProjectUnloadScene", _SC(".xx"));
|
||||
/*#
|
||||
Func: ProjectSceneGetType
|
||||
Proto: ProjectSceneType:ProjectScene
|
||||
Desc: Get a project scene type.
|
||||
#*/
|
||||
sq_register(vm, ProjectSceneGetType, "ProjectSceneGetType", _SC(".x"));
|
||||
/*#
|
||||
Func: ProjectSceneGetInstance
|
||||
Proto: Scene:ProjectScene
|
||||
Desc: Get the scene object of type Scene or UI from a project scene object.
|
||||
Example:
|
||||
local scene = ProjectSceneGetInstace(project_scene) // this project scene encapsulates a 3d scene
|
||||
SceneAddLight(scene, "MyLight")
|
||||
#*/
|
||||
sq_register(vm, ProjectSceneGetInstance, "ProjectSceneGetInstance", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Func: ProjectGetFileName
|
||||
Proto: String:Project
|
||||
Desc: Return the project file name, without the project path.
|
||||
See: ProjectGetFilePath
|
||||
#*/
|
||||
sq_register(vm, ProjectGetFileName, "ProjectGetFileName", _SC(".x"));
|
||||
/*#
|
||||
Func: ProjectGetFilePath
|
||||
Proto: String:Project
|
||||
Desc: Return the project path.
|
||||
See: ProjectGetFileName
|
||||
#*/
|
||||
sq_register(vm, ProjectGetFilePath, "ProjectGetFilePath", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Enum: ProjectSceneType
|
||||
Values: ProjectSceneTypeScene2d,ProjectSceneTypeScene3d
|
||||
#*/
|
||||
sq_pushstring(vm, "ProjectSceneTypeScene2d", -1); sq_pushinteger(vm, ProjectSceneInstance::Type_Scene2d); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "ProjectSceneTypeScene3d", -1); sq_pushinteger(vm, ProjectSceneInstance::Type_Scene3d); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pushstring(vm, "NullItem", -1); CObject::Push(vm, NULL, typetag_Item); sq_newslot(vm, -3, true);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
165
include/modules/script_squirrel/legacy/raytracer_binding.cpp
Normal file
165
include/modules/script_squirrel/legacy/raytracer_binding.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "raytracer/raytracer_core.h"
|
||||
#include "core/graphic_resource_factory.h"
|
||||
#include "core/resource_factories.h"
|
||||
#include "core/geometry.h"
|
||||
#include "picture/pict_io.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
using namespace GS::Raytrace;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger NewRaytracer(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(f, Core::ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_RETURNSAFEPTR(new Raytracer(f->graphic), typetag_Raytracer)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger RaytracerSetScene(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(ray, Raytracer, typetag_Raytracer)
|
||||
__SQ_GETSAFEPTR(scn, S3D::Scene, typetag_Scene3d)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL((ray && scn) ? ray->SetScene(scn) : false)
|
||||
}
|
||||
SQInteger RaytracerTrace(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(4)
|
||||
__SQ_GETSAFEPTR(ray, Raytracer, typetag_Raytracer)
|
||||
__SQ_GETSTRING(file)
|
||||
__SQ_GETINT(width)
|
||||
__SQ_GETINT(height)
|
||||
|
||||
bool r = false;
|
||||
Picture output(width, height);
|
||||
if (ray->Render(output, width, height))
|
||||
r = output.isValid() ? PictureIO::Get().TgaSave(output, file) : false;
|
||||
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(r)
|
||||
}
|
||||
SQInteger RaytracerSetInterlace(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(ray, Raytracer, typetag_Raytracer)
|
||||
__SQ_GETBOOL(interlaced)
|
||||
__SQ_GETBOOL(interlace_even)
|
||||
__SQ_GETEND
|
||||
|
||||
Configuration config = ray->GetConfiguration();
|
||||
config.interlaced = interlaced ? true : false;
|
||||
config.interlace_even = interlace_even ? true : false;
|
||||
ray->SetConfiguration(config);
|
||||
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger RaytracerSetAntialias(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(5)
|
||||
__SQ_GETSAFEPTR(ray, Raytracer, typetag_Raytracer)
|
||||
__SQ_GETBOOL(trace_aa)
|
||||
__SQ_GETINT(aa_sample)
|
||||
__SQ_GETFLOAT(aa_threshold)
|
||||
__SQ_GETBOOL(aa_jitter)
|
||||
__SQ_GETEND
|
||||
|
||||
Configuration config = ray->GetConfiguration();
|
||||
config.trace_aa = trace_aa ? true : false;
|
||||
config.aa_sample = aa_sample;
|
||||
config.aa_threshold = aa_threshold;
|
||||
config.aa_jitter = aa_jitter ? true : false;
|
||||
ray->SetConfiguration(config);
|
||||
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger RaytracerSetGlobalIllum(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(4)
|
||||
__SQ_GETSAFEPTR(ray, Raytracer, typetag_Raytracer)
|
||||
__SQ_GETBOOL(trace_gi)
|
||||
__SQ_GETINT(gi_sample)
|
||||
__SQ_GETINT(indirect_gi_bounce)
|
||||
__SQ_GETEND
|
||||
|
||||
Configuration config = ray->GetConfiguration();
|
||||
config.trace_gi = trace_gi ? true : false;
|
||||
config.gi_sample = gi_sample;
|
||||
config.indirect_gi_bounce = indirect_gi_bounce;
|
||||
ray->SetConfiguration(config);
|
||||
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger RaytracerStartInterlacedSequence(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(ray, Raytracer, typetag_Raytracer)
|
||||
ray->StartInterlacedSequence();
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterRaytracerBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Raytracer
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: RaytracerGeneric
|
||||
Desc: Generic functions
|
||||
#*/
|
||||
/*#
|
||||
Func: NewRaytracer
|
||||
Proto: Raytracer:ResourceFactory
|
||||
Desc: Create a new raytracer instance.
|
||||
#*/
|
||||
sq_register(vm, NewRaytracer, "NewRaytracer", _SC(".x"));
|
||||
/*#
|
||||
Func: RaytracerSetAntialias
|
||||
Proto: void:raytracer,bool enable,int sample_count,float threshold,bool jitter
|
||||
Desc: Set the raytracer antialias output. The number of AA sample can be set and jitered AA selected. Default threshold: 0.015.
|
||||
#*/
|
||||
sq_register(vm, RaytracerSetAntialias, "RaytracerSetAntialias", _SC(".xbinb"));
|
||||
/*#
|
||||
Func: RaytracerSetGlobalIllum
|
||||
Proto: void:raytracer,bool enable,int sample_count,int max_indirect_bounce
|
||||
Desc: Enable the raytracer global illumination. The number of GI sample can be set as well as a maximum number of indirect bounce.
|
||||
#*/
|
||||
sq_register(vm, RaytracerSetGlobalIllum, "RaytracerSetGlobalIllum", _SC(".xbii"));
|
||||
/*#
|
||||
Func: RaytracerSetInterlace
|
||||
Proto: void:raytracer,bool interlaced,bool even_frame
|
||||
Desc: Set the raytracer interlace output. The frame parity is specified as the second parameter.
|
||||
#*/
|
||||
sq_register(vm, RaytracerSetInterlace, "RaytracerSetInterlace", _SC(".xbb"));
|
||||
/*#
|
||||
Func: RaytracerStartInterlacedSequence
|
||||
Proto: void:raytracer
|
||||
Desc: Start an interlaced sequence. This function should be called when beginning a new sequence in order to ensure correct frame parity.
|
||||
#*/
|
||||
sq_register(vm, RaytracerStartInterlacedSequence, "RaytracerStartInterlacedSequence", _SC(".x"));
|
||||
/*#
|
||||
Func: RaytracerSetScene
|
||||
Proto: void:raytracer,scene
|
||||
Desc: Set raytracer scene, this function might be a little slow as it setups a lot data to work with.
|
||||
#*/
|
||||
sq_register(vm, RaytracerSetScene, "RaytracerSetScene", _SC(".xx"));
|
||||
/*#
|
||||
Func: RaytracerTrace
|
||||
Proto: void:raytracer,string out_picture,int width,int height
|
||||
Desc: Raytrace current scene to a Targa picture file. Note that when rendering interlaced sequences one of two calls to this function will return false to notify you that the current frame was only buffered and not saved.
|
||||
#*/
|
||||
sq_register(vm, RaytracerTrace, "RaytracerTrace", _SC(".xsii"));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
1354
include/modules/script_squirrel/legacy/renderer_binding.cpp
Normal file
1354
include/modules/script_squirrel/legacy/renderer_binding.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,288 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "script_squirrel/cobject/matrix_decl.h"
|
||||
#include "core/resource_factories.h"
|
||||
#include "core/graphic_resource_factory.h"
|
||||
#include "core/render_resource_factory.h"
|
||||
#include "core/mixer_resource_factory.h"
|
||||
#include "core/raster_font.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::Script;
|
||||
using namespace GS::Render;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ResourceFactoryLoadPicture(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(f, ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_GETSTRING(name)
|
||||
Picture *p = f->graphic->LoadPicture(name);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(p, typetag_Picture)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ResourceFactoryLoadRasterFont(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(f, ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_GETSTRING(base)
|
||||
__SQ_GETSTRING(name)
|
||||
RasterFont *font = new RasterFont;
|
||||
if (!font)
|
||||
return sq_throwerror(vm, "Failed to allocate raster font object.");
|
||||
font->Load(*f->render, base, name);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNMANAGEDSAFEPTR(font, typetag_RasterFont)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ResourceFactoryNewTexture(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(f, ResourceFactories, typetag_ResourceFactories)
|
||||
Texture *t = f->render->NewTexture();
|
||||
__SQ_RETURNSAFEPTR(t, typetag_Texture)
|
||||
}
|
||||
SQInteger ResourceFactoryLoadTexture(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(f, ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_GETSTRING(name)
|
||||
Texture *t = f->render->LoadTexture(name);
|
||||
if (!t)
|
||||
return sq_throwerror(vm, String::Format("Texture '%s' not found.", name));
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(t, typetag_Texture)
|
||||
}
|
||||
SQInteger ResourceFactoryLoadTextureEx(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(f, ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_GETSTRING(name)
|
||||
__SQ_GETBOOL(bypass_cache)
|
||||
Texture *t = f->render->LoadTexture(name, asbool(bypass_cache));
|
||||
if (!t)
|
||||
return sq_throwerror(vm, String::Format("Texture '%s' not found.", name));
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(t, typetag_Texture)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ResourceFactoryLoadShader(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(f, ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_GETSTRING(name)
|
||||
Render::Shader *s = f->render->LoadShader(name);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(s, typetag_Shader)
|
||||
}
|
||||
SQInteger ResourceFactoryLoadShaderEx(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(f, ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_GETSTRING(name)
|
||||
__SQ_GETBOOL(bypass_cache)
|
||||
Render::Shader *s = f->render->LoadShader(name, asbool(bypass_cache));
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(s, typetag_Shader)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ResourceFactoryLoadGeometry(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(f, ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_GETSTRING(name)
|
||||
Render::Geometry *g = f->render->LoadGeometry(name);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(g, typetag_Geometry)
|
||||
}
|
||||
SQInteger ResourceFactoryLoadGeometryEx(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(f, ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_GETSTRING(name)
|
||||
__SQ_GETBOOL(bypass_cache)
|
||||
Render::Geometry *g = f->render->LoadGeometry(name, asbool(bypass_cache));
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(g, typetag_Geometry)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ResourceFactoryLoadMaterial(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(f, ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_GETSTRING(name)
|
||||
Render::Material *m = f->render->LoadMaterial(name);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(m, typetag_Material)
|
||||
}
|
||||
SQInteger ResourceFactoryLoadMaterialEx(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(f, ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_GETSTRING(name)
|
||||
__SQ_GETBOOL(bypass_cache)
|
||||
Render::Material *m = f->render->LoadMaterial(name, asbool(bypass_cache));
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(m, typetag_Material)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ResourceFactoryLoadSound(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(f, ResourceFactories, typetag_ResourceFactories)
|
||||
__SQ_GETSTRING(name)
|
||||
Audio::Sound *s = f->audio->LoadSound(name);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNSAFEPTR(s, typetag_Sound)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger ResourceFactoryPurge(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(f, ResourceFactories, typetag_ResourceFactories)
|
||||
uint purged = 0;
|
||||
purged += f->graphic->PurgeCache();
|
||||
purged += f->render->PurgeCache();
|
||||
// purged += f->mixer->PurgeCache();
|
||||
__SQ_RETURNINT(purged)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterResourceFactoryBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Resource Factory
|
||||
Desc: A resource factory caches all graphic and render resources used by a project. You can access your project resource factory from any script by using the global variable <b>g_factory</b>.
|
||||
Type: ResourceFactory
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: ResourceFactoryGeneral
|
||||
Desc: Resource Factory General
|
||||
#*/
|
||||
/*#
|
||||
Func: ResourceFactoryPurge
|
||||
Proto: int:ResourceFactory
|
||||
Desc: Call this function to unload from memory all cached resources that are not currently in use.
|
||||
Example:
|
||||
local purged_count = ResourceFactoryPurge(g_factory)
|
||||
print("Resource unloaded: " + purged_count)
|
||||
#*/
|
||||
sq_register(vm, ResourceFactoryPurge, "ResourceFactoryPurge", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: GraphicResourceFactory
|
||||
Desc: Graphic Resources
|
||||
#*/
|
||||
/*#
|
||||
Func: ResourceFactoryLoadPicture
|
||||
Proto: Picture:ResourceFactory,String name
|
||||
Desc: Load a picture from a graphic resource factory, this function use the resource cache to prevent redundant loads of the same resource.
|
||||
See: PictureLoad
|
||||
#*/
|
||||
sq_register(vm, ResourceFactoryLoadPicture, "ResourceFactoryLoadPicture", _SC(".xs"));
|
||||
|
||||
/*#
|
||||
Section: RenderResourceFactory
|
||||
Desc: Render Resources
|
||||
#*/
|
||||
/*#
|
||||
Func: ResourceFactoryLoadRasterFont
|
||||
Proto: RasterFont:ResourceFactory,String name
|
||||
Desc: Load a raster font from a resource factory.
|
||||
#*/
|
||||
sq_register(vm, ResourceFactoryLoadRasterFont, "ResourceFactoryLoadRasterFont", _SC(".xss"));
|
||||
|
||||
/*#
|
||||
Func: ResourceFactoryNewTexture
|
||||
Proto: Texture:ResourceFactory
|
||||
Desc: Create a new texture from a resource factory.
|
||||
#*/
|
||||
sq_register(vm, ResourceFactoryNewTexture, "ResourceFactoryNewTexture", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Func: ResourceFactoryLoadShader
|
||||
Proto: Shader:ResourceFactory,String name
|
||||
Desc: Load a shader from a resource factory.
|
||||
#*/
|
||||
sq_register(vm, ResourceFactoryLoadShader, "ResourceFactoryLoadShader", _SC(".xs"));
|
||||
/*#
|
||||
Func: ResourceFactoryLoadShaderEx
|
||||
Proto: Shader:ResourceFactory,String name,bool bypass_cache
|
||||
Desc: Load a shader from a resource factory, optionally bypassing the factory cache.
|
||||
#*/
|
||||
sq_register(vm, ResourceFactoryLoadShaderEx, "ResourceFactoryLoadShaderEx", _SC(".xsb"));
|
||||
|
||||
/*#
|
||||
Func: ResourceFactoryLoadTexture
|
||||
Proto: Texture:ResourceFactory,String name
|
||||
Desc: Load a texture from a resource factory.
|
||||
#*/
|
||||
sq_register(vm, ResourceFactoryLoadTexture, "ResourceFactoryLoadTexture", _SC(".xs"));
|
||||
/*#
|
||||
Func: ResourceFactoryLoadTextureEx
|
||||
Proto: Texture:ResourceFactory,String name,bool bypass_cache
|
||||
Desc: Load a texture from a resource factory, optionally bypassing the factory cache.
|
||||
#*/
|
||||
sq_register(vm, ResourceFactoryLoadTextureEx, "ResourceFactoryLoadTextureEx", _SC(".xsb"));
|
||||
|
||||
/*#
|
||||
Func: ResourceFactoryLoadGeometry
|
||||
Proto: Texture:ResourceFactory,String name
|
||||
Desc: Load a geometry from a resource factory.
|
||||
#*/
|
||||
sq_register(vm, ResourceFactoryLoadGeometry, "ResourceFactoryLoadGeometry", _SC(".xs"));
|
||||
/*#
|
||||
Func: ResourceFactoryLoadGeometryEx
|
||||
Proto: Texture:ResourceFactory,String name,bool bypass_cache
|
||||
Desc: Load a geometry from a resource factory, optionally bypassing the factory cache.
|
||||
#*/
|
||||
sq_register(vm, ResourceFactoryLoadGeometryEx, "ResourceFactoryLoadGeometryEx", _SC(".xsb"));
|
||||
|
||||
/*#
|
||||
Func: ResourceFactoryLoadMaterial
|
||||
Proto: Material:ResourceFactory,String name
|
||||
Desc: Load a material from a resource factory.
|
||||
#*/
|
||||
sq_register(vm, ResourceFactoryLoadMaterial, "ResourceFactoryLoadMaterial", _SC(".xs"));
|
||||
|
||||
/*#
|
||||
Func: ResourceFactoryLoadMaterialEx
|
||||
Proto: Material:ResourceFactory,String name,bool bypass_cache
|
||||
Desc: Load a material from a resource factory, optionally bypassing the factory cache.
|
||||
#*/
|
||||
sq_register(vm, ResourceFactoryLoadMaterialEx, "ResourceFactoryLoadMaterialEx", _SC(".xsb"));
|
||||
|
||||
/*#
|
||||
Section: MixerResourceFactory
|
||||
Desc: Mixer Resources
|
||||
#*/
|
||||
/*#
|
||||
Func: ResourceFactoryLoadSound
|
||||
Proto: Sound:ResourceFactory,String name
|
||||
Desc: Load a sound from a resource factory.
|
||||
#*/
|
||||
sq_register(vm, ResourceFactoryLoadSound, "ResourceFactoryLoadSound", _SC(".xs"));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
1744
include/modules/script_squirrel/legacy/scene_binding.cpp
Normal file
1744
include/modules/script_squirrel/legacy/scene_binding.cpp
Normal file
File diff suppressed because it is too large
Load Diff
44
include/modules/script_squirrel/legacy/sound_binding.cpp
Normal file
44
include/modules/script_squirrel/legacy/sound_binding.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "squirrel.h"
|
||||
#include "script_squirrel/legacy/binding_helpers.h"
|
||||
#include "core/sound.h"
|
||||
|
||||
using namespace GS::Audio;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger SoundGetDuration(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(s, Sound, typetag_Sound)
|
||||
__SQ_RETURNINT(s->mixer_data.IsValid() ? s->mixer_data->Get()->duration.toMs() : -1)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterSoundBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Sound
|
||||
Desc: A sound object stores audio data that can be played back by the sound mixer.
|
||||
Type: Sound
|
||||
Related: Mixer
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: SoundGeneric
|
||||
Desc: Generic functions
|
||||
#*/
|
||||
/*#
|
||||
Func: SoundGetDuration
|
||||
Proto: int:sound
|
||||
Desc: Returns the sound duration in milliseconds.
|
||||
#*/
|
||||
sq_register(vm, SoundGetDuration, "SoundGetDuration", _SC(".x"));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
549
include/modules/script_squirrel/legacy/squirrel_binding.cpp
Normal file
549
include/modules/script_squirrel/legacy/squirrel_binding.cpp
Normal file
@ -0,0 +1,549 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
|
||||
#include "squirrel.h"
|
||||
#include "script_squirrel/cobject/uc_binding.h"
|
||||
#include "script_squirrel/cobject/cobject.h"
|
||||
#include "script_squirrel/cobject/vector_decl.h"
|
||||
#include "script_squirrel/cobject/uv_decl.h"
|
||||
|
||||
#include "squirrel_binding.h"
|
||||
#include "binding_helpers.h"
|
||||
|
||||
#if __PLATFORM_NINTENDO_WII__
|
||||
#include "platform/wii/script/wii_binding.h"
|
||||
#endif
|
||||
#include "geometry/bounding_box.h"
|
||||
#include "color/color.h"
|
||||
#include "geometry/rect.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Script {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static bool BindingError(HSQUIRRELVM vm, const char *msg)
|
||||
{
|
||||
// if (sq_getforeignptr(vm))
|
||||
// ((Script::VM *)sq_getforeignptr(vm))->Kill();
|
||||
SquirrelVM::DumpCallStack(vm, String::Format("Binding error: %s", msg).c_str());
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool CreateClassInstance(HSQUIRRELVM vm, const char *class_name, bool call)
|
||||
{
|
||||
sq_pushroottable(vm);
|
||||
sq_pushstring(vm, class_name, -1);
|
||||
if (SQ_FAILED(sq_get(vm, -2)))
|
||||
{
|
||||
sq_pop(vm, 1);
|
||||
return BindingError(vm, String::Format("Class '%s' is not declared.", class_name).c_str());
|
||||
}
|
||||
if (call)
|
||||
{
|
||||
sq_pushroottable(vm);
|
||||
if (SQ_FAILED(sq_call(vm, 1, SQTrue, SQTrue)))
|
||||
{
|
||||
sq_pop(vm, 1);
|
||||
return BindingError(vm, String::Format("Failed to instantiate class '%s'.", class_name).c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
sq_createinstance(vm, -1);
|
||||
sq_remove(vm, -2); // Remove root table.
|
||||
sq_remove(vm, -2); // Remove class.
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void PushColor(HSQUIRRELVM vm, const Color &c)
|
||||
{
|
||||
if (!CreateClassInstance(vm, "Vector", true))
|
||||
BindingError(vm, "Failed to create Vector instance.");
|
||||
SetTableKey("x", sq_pushfloat, -1, c.x);
|
||||
SetTableKey("y", sq_pushfloat, -1, c.y);
|
||||
SetTableKey("z", sq_pushfloat, -1, c.z);
|
||||
SetTableKey("w", sq_pushfloat, -1, c.w);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void PushVector2(HSQUIRRELVM vm, const Vector2 &v)
|
||||
{
|
||||
if (!CreateClassInstance(vm, "Vector2", true))
|
||||
BindingError(vm, "Failed to create Vector2 instance.");
|
||||
SetTableKey("x", sq_pushfloat, -1, v.x);
|
||||
SetTableKey("y", sq_pushfloat, -1, v.y);
|
||||
}
|
||||
void GetVector2(HSQUIRRELVM vm, SQInteger idx, Vector2 &v)
|
||||
{
|
||||
SQFloat x, y;
|
||||
GetTableKey("x", sq_getfloat, idx, x)
|
||||
GetTableKey("y", sq_getfloat, idx, y)
|
||||
v.Set(x, y);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void PushVector(HSQUIRRELVM vm, const Vector4 &v, bool push_w)
|
||||
{
|
||||
push_Vector(vm, v);
|
||||
}
|
||||
void GetVector(HSQUIRRELVM v, SQInteger idx, Vector4 &vo, bool get_w)
|
||||
{
|
||||
_CHECK_INST_PARAM_RAW(pv, idx, Vector4, Vector);
|
||||
vo = *pv;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void PushUV(HSQUIRRELVM vm, const Vector2 &uv)
|
||||
{
|
||||
if (!CreateClassInstance(vm, "UV", true))
|
||||
BindingError(vm, "Failed to create UV instance.");
|
||||
SetTableKey("u", sq_pushfloat, -1, uv.x);
|
||||
SetTableKey("v", sq_pushfloat, -1, uv.y);
|
||||
}
|
||||
void GetUV(HSQUIRRELVM v, SQInteger idx, Vector2 &uv)
|
||||
{
|
||||
_CHECK_INST_PARAM_RAW(pv, idx, Vector2, UV);
|
||||
uv = *pv;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void PushMinMax(HSQUIRRELVM vm, const MinMax &v)
|
||||
{
|
||||
if (!CreateClassInstance(vm, "MinMax", true))
|
||||
BindingError(vm, "Failed to create MinMax instance.");
|
||||
|
||||
sq_pushstring(vm, "min", -1);
|
||||
sq_get(vm, -2);
|
||||
SetTableKey("x", sq_pushfloat, -1, v.mn.x)
|
||||
SetTableKey("y", sq_pushfloat, -1, v.mn.y)
|
||||
SetTableKey("z", sq_pushfloat, -1, v.mn.z)
|
||||
sq_pop(vm, 1);
|
||||
|
||||
sq_pushstring(vm, "max", -1);
|
||||
sq_get(vm, -2);
|
||||
SetTableKey("x", sq_pushfloat, -1, v.mx.x)
|
||||
SetTableKey("y", sq_pushfloat, -1, v.mx.y)
|
||||
SetTableKey("z", sq_pushfloat, -1, v.mx.z)
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
void GetMinMax(HSQUIRRELVM vm, SQInteger idx, MinMax &v)
|
||||
{
|
||||
sq_pushstring(vm, "min", -1);
|
||||
sq_get(vm, -2);
|
||||
GetVector(vm, -1, v.mn);
|
||||
sq_pop(vm, 1);
|
||||
|
||||
sq_pushstring(vm, "max", -1);
|
||||
sq_get(vm, -2);
|
||||
GetVector(vm, -1, v.mx);
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void PushRect(HSQUIRRELVM vm, const fRect &r)
|
||||
{
|
||||
if (!CreateClassInstance(vm, "Rect"))
|
||||
BindingError(vm, "Failed to create Rect instance.");
|
||||
SetTableKey("sx", sq_pushfloat, -1, r.sx);
|
||||
SetTableKey("sy", sq_pushfloat, -1, r.sy);
|
||||
SetTableKey("ex", sq_pushfloat, -1, r.ex);
|
||||
SetTableKey("ey", sq_pushfloat, -1, r.ey);
|
||||
}
|
||||
void GetRect(HSQUIRRELVM vm, SQInteger idx, fRect &r)
|
||||
{
|
||||
SQFloat sx, sy, ex, ey;
|
||||
GetTableKey("sx", sq_getfloat, idx, sx)
|
||||
GetTableKey("sy", sq_getfloat, idx, sy)
|
||||
GetTableKey("ex", sq_getfloat, idx, ex)
|
||||
GetTableKey("ey", sq_getfloat, idx, ey)
|
||||
r.Set(sx, sy, ex, ey);
|
||||
}
|
||||
void PushRect(HSQUIRRELVM vm, const iRect &r)
|
||||
{ PushRect(vm, r.AsFloat()); }
|
||||
void GetRect(HSQUIRRELVM vm, SQInteger idx, iRect &r)
|
||||
{
|
||||
fRect t;
|
||||
GetRect(vm, idx, t);
|
||||
r.Set(int(t.sx), int(t.sy), int(t.ex), int(t.ey));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void sq_register(HSQUIRRELVM v, SQFUNCTION f, const char *fname, const SQChar *mask)
|
||||
{
|
||||
sq_pushroottable(v);
|
||||
sq_pushstring(v, (const SQChar *)fname, -1);
|
||||
sq_newclosure(v, f, 0); // Create a new function.
|
||||
sq_setnativeclosurename(v, -1, fname);
|
||||
sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, mask);
|
||||
sq_newslot(v, -3, false);
|
||||
sq_pop(v, 1); // Pop the root table.
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // Script
|
||||
} // GS
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
//------------------------------------------
|
||||
SQInteger SQAssert(HSQUIRRELVM vm)
|
||||
//------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETBOOL(c)
|
||||
__SQ_GETSTRING(d)
|
||||
if (!c)
|
||||
return sq_throwerror(vm, d);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
SQInteger SQPow(HSQUIRRELVM vm)
|
||||
//---------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETFLOAT(v)
|
||||
__SQ_GETFLOAT(p)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNFLOAT(pow(v, p))
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
SQInteger SQExp(HSQUIRRELVM vm)
|
||||
//---------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETFLOAT(v)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNFLOAT(exp(v))
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
SQInteger SQMod(HSQUIRRELVM vm)
|
||||
//---------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETINT(v)
|
||||
__SQ_GETINT(m)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNINT(v % m)
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
SQInteger SQAbsMod(HSQUIRRELVM vm)
|
||||
//------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETINT(v)
|
||||
__SQ_GETINT(m)
|
||||
__SQ_GETEND
|
||||
v %= m;
|
||||
if (v < 0)
|
||||
v = m + v;
|
||||
__SQ_RETURNINT(v)
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
SQInteger ObjectIsValid(HSQUIRRELVM vm)
|
||||
//-----------------------------------------------
|
||||
{
|
||||
void *p;
|
||||
if (!CObject::Get(vm, -1, &p))
|
||||
return -1;
|
||||
sq_pop(vm, 1);
|
||||
__SQ_RETURNBOOL(asbool(p));
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
SQInteger ObjectIsSame(HSQUIRRELVM vm)
|
||||
//----------------------------------------------
|
||||
{
|
||||
void *a, *b;
|
||||
if (!CObject::Get(vm, -2, &a) || !CObject::Get(vm, -1, &b))
|
||||
return -1;
|
||||
sq_pop(vm, 2);
|
||||
__SQ_RETURNBOOL(a == b);
|
||||
}
|
||||
|
||||
//----------------------------------------------
|
||||
SQInteger ShellExecute(HSQUIRRELVM vm)
|
||||
//----------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSTRING(path)
|
||||
__SQ_GETSTRING(parm)
|
||||
|
||||
int r = -1;
|
||||
|
||||
#if __PLATFORM_WINDOWS__
|
||||
if (path)
|
||||
{
|
||||
String cmd = parm ? String::Format("%s %s", path, parm).c_str() : path;
|
||||
__LOG_H__ << "Execute command '" << cmd << "'\n\n";
|
||||
|
||||
#if 0
|
||||
char szBuffer[_MAX_PATH * 10 + 1];
|
||||
|
||||
DWORD dw;
|
||||
HANDLE hIn, hOut;
|
||||
PROCESS_INFORMATION pi;
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
STARTUPINFO si;
|
||||
|
||||
if (CreatePipe(&hIn, &hOut, NULL, sizeof(szBuffer) * 2))
|
||||
{
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
|
||||
si.wShowWindow = SW_HIDE;
|
||||
si.hStdOutput = hOut;
|
||||
si.hStdError = hOut;
|
||||
|
||||
//if (!CreateProcess("C:\\WINDOWS\\system32\\cmd.exe", (LPSTR)cmd.c_str(), NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
|
||||
if (!CreateProcess(NULL, (LPSTR)cmd.c_str(), NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
|
||||
__LOG_N__ << "Couldn't create process: " << GetLastError() << "\n";
|
||||
else
|
||||
{
|
||||
CloseHandle(hOut);
|
||||
__LOG_N__ << "Reading ShellExecute...\n";
|
||||
|
||||
forever
|
||||
{
|
||||
if (ReadFile(hIn, szBuffer, sizeof(szBuffer) - 1, &dw, NULL) == 0)
|
||||
{
|
||||
if (GetLastError() == ERROR_NO_DATA)
|
||||
Sleep(1);
|
||||
|
||||
else if (GetLastError() == ERROR_BROKEN_PIPE)
|
||||
{
|
||||
GetExitCodeProcess(pi.hProcess, &dw);
|
||||
r = dw;
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (dw > 0)
|
||||
{
|
||||
szBuffer[dw] = 0;
|
||||
__LOG__ << szBuffer << "\n";
|
||||
}
|
||||
|
||||
if ((GetExitCodeProcess(pi.hProcess, &dw) == 0) || (dw != STILL_ACTIVE))
|
||||
{
|
||||
r = dw;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(hIn);
|
||||
}
|
||||
else {
|
||||
__LOG_N__ << "Couldn't create pipe: " << GetLastError() << "\n";
|
||||
}
|
||||
#else
|
||||
char psBuffer[256];
|
||||
FILE *iopipe;
|
||||
|
||||
if ((iopipe = _popen(cmd.c_str(), "r" )) != 0)
|
||||
while (!feof(iopipe))
|
||||
if (fgets(psBuffer, 256, iopipe))
|
||||
__LOG__ << psBuffer;
|
||||
|
||||
r = _pclose(iopipe);
|
||||
#endif
|
||||
}
|
||||
#elif __PLATFORM_OSX__
|
||||
__LOG_E__ << "ShellExecute(): STUB\n";
|
||||
#elif __PLATFORM_LINUX__
|
||||
r = path ? system(parm ? String::Format("%s %s", path, parm).c_str() : path) : -1;
|
||||
#endif
|
||||
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNINT(r)
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------
|
||||
SQInteger Sleep(HSQUIRRELVM vm)
|
||||
//---------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETINT(ms)
|
||||
__SQ_GETEND
|
||||
Platform::Get().Sleep(ms);
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
void RegisterAllSquirrelBinding(HSQUIRRELVM vm)
|
||||
//------------------------------------------------------------
|
||||
{
|
||||
/*#
|
||||
Topic: Script
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: ScriptDebug
|
||||
Desc: Debugging
|
||||
#*/
|
||||
/*#
|
||||
Func: __Assert
|
||||
Proto: void:bool,string
|
||||
Desc: Assert an expression, throw an engine exception and suspend the VM if not verified.
|
||||
#*/
|
||||
sq_register(vm, SQAssert, "__Assert", _SC(".bs"));
|
||||
|
||||
/*#
|
||||
Section: ScriptGeneric
|
||||
Desc: Generic
|
||||
#*/
|
||||
/*#
|
||||
Func: SQPow
|
||||
Proto: float:float value,float pow
|
||||
Desc: Returns value raised to power.
|
||||
#*/
|
||||
sq_register(vm, SQPow, "Pow", _SC(".ff"));
|
||||
/*#
|
||||
Func: SQExp
|
||||
Proto: float:float value
|
||||
Desc: Returns value in exponential .
|
||||
#*/
|
||||
sq_register(vm, SQExp, "Exp", _SC(".f"));
|
||||
/*#
|
||||
Func: SQMod
|
||||
Proto: int:int value,int divider
|
||||
Desc: Returns integer modulo of a value.
|
||||
#*/
|
||||
sq_register(vm, SQMod, "Mod", _SC(".ii"));
|
||||
/*#
|
||||
Func: SQAbsMod
|
||||
Proto: int:int value,int divider
|
||||
Desc: Returns integer modulo of the absolute of a given value.
|
||||
#*/
|
||||
sq_register(vm, SQAbsMod, "AbsMod", _SC(".ii"));
|
||||
/*#
|
||||
Func: ObjectIsValid
|
||||
Proto: bool:Object
|
||||
Desc: Returns true if the given engine object is valid, false otherwise.<br>This function can be used to test the validity of all engine types like geometry, material, item, scene and others.
|
||||
#*/
|
||||
sq_register(vm, ObjectIsValid, "ObjectIsValid", _SC(".x"));
|
||||
/*#
|
||||
Func: ObjectIsSame
|
||||
Proto: bool:Object,Object
|
||||
Desc: Returns true if two given engine object references are pointing to the same object.
|
||||
#*/
|
||||
sq_register(vm, ObjectIsSame, "ObjectIsSame", _SC(".xx"));
|
||||
|
||||
/*#
|
||||
Topic: System
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: SystemGeneric
|
||||
Desc: Generic
|
||||
#*/
|
||||
/*#
|
||||
Func: ShellExecute
|
||||
Proto: int:string path,string param
|
||||
Desc: Execute an external program, returns its return code.
|
||||
#*/
|
||||
sq_register(vm, ShellExecute, "ShellExecute", _SC(".ss"));
|
||||
|
||||
|
||||
sq_register(vm, Sleep, "_Sleep", _SC(".i"));
|
||||
|
||||
// Legacy support.
|
||||
#if 1
|
||||
sq_register(vm, ObjectIsValid, "AIPathIsValid", _SC(".x"));
|
||||
sq_register(vm, ObjectIsValid, "GeometryIsValid", _SC(".x"));
|
||||
sq_register(vm, ObjectIsValid, "ItemIsValid", _SC(".x"));
|
||||
sq_register(vm, ObjectIsValid, "MetatagIsValid", _SC(".x"));
|
||||
sq_register(vm, ObjectIsValid, "TextureIsValid", _SC(".x"));
|
||||
sq_register(vm, ObjectIsValid, "WidgetIsValid", _SC(".x"));
|
||||
sq_register(vm, ObjectIsValid, "WindowIsValid", _SC(".x"));
|
||||
#endif
|
||||
|
||||
sq_pushroottable(vm);
|
||||
|
||||
/*#
|
||||
Enum: SystemConstant
|
||||
Values: SystemClockFrequency
|
||||
#*/
|
||||
sq_pushstring(vm, "SystemClockFrequency", -1); sq_pushinteger(vm, Platform::Get().GetClockFrequency()); sq_newslot(vm, -3, true);
|
||||
|
||||
// Register engine types.
|
||||
for (int n = 0; n < typetag_End; ++n)
|
||||
{
|
||||
String type_string = String::Format("EngineType%s", CObjectTypeToString((CObjectType)n));
|
||||
sq_pushstring(vm, type_string.TrimChar(' ').c_str(), -1); sq_pushinteger(vm, n); sq_newslot(vm, -3, true);
|
||||
}
|
||||
|
||||
// Newer faster bindings.
|
||||
RegisterUCBinding(vm);
|
||||
|
||||
//
|
||||
RegisterClockBinding(vm);
|
||||
RegisterMatrixBinding(vm);
|
||||
RegisterAnimationBinding(vm);
|
||||
RegisterAIBinding(vm);
|
||||
RegisterSystemBinding(vm);
|
||||
RegisterRendererBinding(vm);
|
||||
RegisterMixerBinding(vm);
|
||||
RegisterSceneBinding(vm);
|
||||
RegisterInstanceBinding(vm);
|
||||
RegisterGroupBinding(vm);
|
||||
RegisterCameraBinding(vm);
|
||||
RegisterObjectBinding(vm);
|
||||
RegisterMaterialBinding(vm);
|
||||
RegisterLightBinding(vm);
|
||||
RegisterProfilerBinding(vm);
|
||||
RegisterItemBinding(vm);
|
||||
RegisterMotionBinding(vm);
|
||||
RegisterCollisionBinding(vm);
|
||||
RegisterPhysicBinding(vm);
|
||||
RegisterPictureBinding(vm);
|
||||
RegisterTextureBinding(vm);
|
||||
RegisterSoundBinding(vm);
|
||||
RegisterGeometryBinding(vm);
|
||||
RegisterIOBinding(vm);
|
||||
RegisterUIBinding(vm);
|
||||
RegisterNMLBinding(vm);
|
||||
RegisterResourceFactoryBinding(vm);
|
||||
RegisterRaytracerBinding(vm);
|
||||
RegisterProjectBinding(vm);
|
||||
RegisterTriggerBinding(vm);
|
||||
RegisterEmitterBinding(vm);
|
||||
RegisterHashBinding(vm);
|
||||
RegisterHTTPBinding(vm);
|
||||
RegisterFontBinding(vm);
|
||||
RegisterPlatformBinding(vm);
|
||||
RegisterMaterialShaderBinding(vm);
|
||||
|
||||
#if __PLATFORM_NINTENDO_WII__
|
||||
RegisterWiiBinding(vm);
|
||||
#endif
|
||||
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
@ -27,7 +27,6 @@ void RegisterFontBinding(HSQUIRRELVM);
|
||||
void RegisterGroupBinding(HSQUIRRELVM);
|
||||
void RegisterHashBinding(HSQUIRRELVM);
|
||||
void RegisterHTTPBinding(HSQUIRRELVM);
|
||||
void RegisterWebSocketBinding(HSQUIRRELVM);
|
||||
void RegisterInstanceBinding(HSQUIRRELVM);
|
||||
void RegisterIOBinding(HSQUIRRELVM);
|
||||
void RegisterItemBinding(HSQUIRRELVM);
|
||||
|
||||
254
include/modules/script_squirrel/legacy/system_binding.cpp
Normal file
254
include/modules/script_squirrel/legacy/system_binding.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifdef __PLATFORM_WINDOWS__
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOGDI
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "squirrel_binding.h"
|
||||
#include "binding_helpers.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "filesystem/io_memory.h"
|
||||
#include "filesystem/io_cfile.h"
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "rand/rand.h"
|
||||
#include "platform.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger SystemGetClock(HSQUIRRELVM vm) {
|
||||
__SQ_RETURNINT(Platform::Get().GetClock()) }
|
||||
SQInteger SystemGarbageCollect(HSQUIRRELVM vm) {
|
||||
sq_collectgarbage(vm);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger SystemGetClockFrequency(HSQUIRRELVM vm)
|
||||
{ __SQ_RETURNINT(Platform::Get().GetClockFrequency()) }
|
||||
SQInteger SystemGetLocale(HSQUIRRELVM vm)
|
||||
{ __SQ_RETURNSTRING(/*Platform::Get().GetLocale()*/"STUB") }
|
||||
SQInteger SystemGetPlatform(HSQUIRRELVM vm)
|
||||
{ __SQ_RETURNSTRING(Platform::Get().GetName()) }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger SystemSeedRand(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETINT(seed))
|
||||
Random::Seed(seed);
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger SystemRand(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETINT(range))
|
||||
__SQ_RETURNINT(Random::Rand(range));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger SystemShowCursor(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETBOOL(show))
|
||||
#ifdef __PLATFORM_WINDOWS__
|
||||
ShowCursor(show);
|
||||
#endif
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger SystemSleep(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETINT(ms))
|
||||
Platform::Get().Sleep(ms);
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger SystemSetProcessAffinity(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLE(__SQ_GETINT(num_thread))
|
||||
HANDLE process = GetCurrentProcess();
|
||||
DWORD_PTR processAffinityMask = 1 << 0;
|
||||
for (int i = 1; i < num_thread; ++i)
|
||||
processAffinityMask |= (1 << i);
|
||||
|
||||
BOOL success = SetProcessAffinityMask(process, processAffinityMask);
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger SystemMountLocalPath(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSTRING(mount_point)
|
||||
__SQ_GETSTRING(local_path)
|
||||
bool r = Platform::Get().io->Mount(new IO::CFile(local_path), mount_point);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(r)
|
||||
}
|
||||
SQInteger SystemHasMountPoint(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(mount_point)
|
||||
bool r = asbool(Platform::Get().io->GetIOSystem(mount_point));
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(r)
|
||||
}
|
||||
SQInteger GetPathFromMountPoint(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(mount_point)
|
||||
__SQ_GETEND
|
||||
IO::Base* base = Platform::Get().io->GetIOSystem(mount_point);
|
||||
if(base == NULL)
|
||||
__SQ_RETURNSTRING("")
|
||||
else
|
||||
__SQ_RETURNSTRING(base->MapToAbsolute(""))
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger SystemLoadBindingPlugin(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(shared_lib_path)
|
||||
|
||||
SquirrelVM *sq = (SquirrelVM *)sq_getforeignptr(vm);
|
||||
int code_error = 0;
|
||||
Script::BindingPluginManager::Plugin *plugin = sq->binding_plugins.LoadPlugin(shared_lib_path, &code_error);
|
||||
|
||||
if (plugin == NULL)
|
||||
return sq_throwerror(vm, "Failed to load binding library.");
|
||||
|
||||
else
|
||||
{
|
||||
Script::IScriptBinding *binding = sq->binding_plugins.CreatePluginInterface(plugin);
|
||||
binding->RegisterBinding(*sq);
|
||||
}
|
||||
|
||||
__SQ_GETEND
|
||||
__SQ_RETURNBOOL(true)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterSystemBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: System
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: System
|
||||
Desc: System functions
|
||||
#*/
|
||||
/*#
|
||||
Func: SystemSleep
|
||||
Proto: void:int
|
||||
Desc: Sleep the current thread for a specified number of milliseconds.
|
||||
#*/
|
||||
sq_register(vm, SystemSleep, "SystemSleep", _SC(".i"));
|
||||
|
||||
/*#
|
||||
Func: SystemSetProcessAffinity
|
||||
Proto: void:int
|
||||
Desc: Set the number of thread affinity for the process simulator.
|
||||
#*/
|
||||
sq_register(vm, SystemSetProcessAffinity, "SystemSetProcessAffinity", _SC(".i"));
|
||||
|
||||
/*#
|
||||
Func: SystemGetClock
|
||||
Proto: int:
|
||||
Desc: Return the raw system clock.
|
||||
#*/
|
||||
sq_register(vm, SystemGetClock, "SystemGetClock", _SC("."));
|
||||
/*#
|
||||
Func: SystemGarbageCollect
|
||||
Proto: void:
|
||||
Desc: garbage collect.
|
||||
#*/
|
||||
sq_register(vm, SystemGarbageCollect, "SystemGarbageCollect", _SC("."));
|
||||
/*#
|
||||
Func: SystemGetClockFrequency
|
||||
Proto: int:
|
||||
Desc: Return the system clock frequency.
|
||||
#*/
|
||||
sq_register(vm, SystemGetClockFrequency, "SystemGetClockFrequency", _SC("."));
|
||||
/*#
|
||||
Func: SystemGetLocale
|
||||
Proto: string:
|
||||
Desc: Return the system language description in a string ("FR","EN","ES","NL","IT").
|
||||
#*/
|
||||
sq_register(vm, SystemGetLocale, "SystemGetLocale", _SC("."));
|
||||
/*#
|
||||
Func: SystemGetPlatform
|
||||
Proto: string:
|
||||
Desc: Return the current platform ("Win32", "Linux32", "Wii").
|
||||
#*/
|
||||
sq_register(vm, SystemGetPlatform, "SystemGetPlatform", _SC("."));
|
||||
|
||||
/*#
|
||||
Func: SystemRand
|
||||
Proto: int:int range
|
||||
Desc: Return a random number between [0;range].
|
||||
#*/
|
||||
sq_register(vm, SystemRand, "SystemRand", _SC(".n"));
|
||||
/*#
|
||||
Func: SystemSeedRand
|
||||
Proto: void:int seed
|
||||
Desc: Initialize the random number sequence with a given seed.
|
||||
#*/
|
||||
sq_register(vm, SystemSeedRand, "SystemSeedRand", _SC(".n"));
|
||||
|
||||
/*#
|
||||
Func: SystemShowCursor
|
||||
Proto: void:bool show
|
||||
Desc: Show/hide the platform cursor.
|
||||
#*/
|
||||
sq_register(vm, SystemShowCursor, "SystemShowCursor", _SC(".b"));
|
||||
|
||||
/*#
|
||||
Func: SystemMountLocalPath
|
||||
Proto: bool:String local_path,String mount_point
|
||||
Desc: Mount a local path under a specific mount point.
|
||||
Example: SystemMountLocalPath("d:/test/", "@test/") // "d:/test/a.jpg" can now be accessed as "@test/a.jpg".
|
||||
#*/
|
||||
sq_register(vm, SystemMountLocalPath, "SystemMountLocalPath", _SC(".ss"));
|
||||
/*#
|
||||
Func: SystemHasMountPoint
|
||||
Proto: bool:string mount_point
|
||||
Desc: Returns true if the specified mount point exists.
|
||||
#*/
|
||||
sq_register(vm, SystemHasMountPoint, "SystemHasMountPoint", _SC(".s"));
|
||||
/*#
|
||||
Func: GetPathFromMountPoint
|
||||
Proto: string:string mount_point
|
||||
Desc: Returns path if the specified mount point exists.
|
||||
#*/
|
||||
sq_register(vm, GetPathFromMountPoint, "GetPathFromMountPoint", _SC(".s"));
|
||||
|
||||
/*#
|
||||
Func: SystemLoadBindingPlugin
|
||||
Proto: bool:string library_path
|
||||
Desc: Load a script binding API from a shared library.
|
||||
#*/
|
||||
sq_register(vm, SystemLoadBindingPlugin, "SystemLoadBindingPlugin", _SC(".s"));
|
||||
|
||||
/*#
|
||||
Enum: HardwareButton
|
||||
Values: HardwareButtonHome,HardwareButtonMenu,HardwareButtonBack
|
||||
#*/
|
||||
sq_pushstring(vm, "HardwareButtonHome", -1); sq_pushinteger(vm, 0); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "HardwareButtonMenu", -1); sq_pushinteger(vm, 1); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "HardwareButtonBack", -1); sq_pushinteger(vm, 2); sq_newslot(vm, -3, true);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
158
include/modules/script_squirrel/legacy/texture_binding.cpp
Normal file
158
include/modules/script_squirrel/legacy/texture_binding.cpp
Normal file
@ -0,0 +1,158 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "core/render_data.h"
|
||||
#include "core/graphic_resource_factory.h"
|
||||
#include "picture/pict.h"
|
||||
|
||||
using namespace GS::Render;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger TextureSetWrapping(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETSAFEPTR(t, Texture, typetag_Texture)
|
||||
__SQ_GETBOOL(wrap_u)
|
||||
__SQ_GETBOOL(wrap_v)
|
||||
__SQ_GETEND
|
||||
t->SetWrapping(wrap_u ? TextureParm::WrapRepeat : TextureParm::WrapClamp, wrap_v ? TextureParm::WrapRepeat : TextureParm::WrapClamp);
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger TextureSetStreamState(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(t, Texture, typetag_Texture)
|
||||
__SQ_GETINT(stream_state)
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger TextureRewindStream(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(t, Texture, typetag_Texture)
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger TextureGetWidth(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(t, Texture, typetag_Texture)
|
||||
__SQ_RETURNINT(t->GetWidth())
|
||||
}
|
||||
SQInteger TextureGetHeight(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(t, Texture, typetag_Texture)
|
||||
__SQ_RETURNINT(t->GetHeight())
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger TextureUpdate(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(t, Texture, typetag_Texture)
|
||||
__SQ_GETSAFEPTR(p, GS::Picture, typetag_Picture)
|
||||
__SQ_GETEND
|
||||
//__SQ_RETURNBOOL(t->Create((const char *)p->GetData(), p->GetWidth(), p->GetHeight()))
|
||||
t->Blit((const char *)p->GetData(), p->GetWidth(), p->GetHeight());
|
||||
__SQ_RETURN
|
||||
}
|
||||
SQInteger TextureRelease(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(t, Texture, typetag_Texture)
|
||||
t->Free();
|
||||
__SQ_RETURN
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterTextureBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Texture
|
||||
Type: Texture
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: TextureStream
|
||||
Desc: Data streaming
|
||||
#*/
|
||||
/*#
|
||||
Func: TextureSetStreamState
|
||||
Proto: void:texture,StreamState state
|
||||
Desc: Set the texture stream state.
|
||||
#*/
|
||||
sq_register(vm, TextureSetStreamState, "TextureSetStreamState", _SC(".xi"));
|
||||
/*#
|
||||
Func: TextureRewindStream
|
||||
Proto: void:texture
|
||||
Desc: Rewind texture stream.
|
||||
#*/
|
||||
sq_register(vm, TextureRewindStream, "TextureRewindStream", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Section: TextureSampling
|
||||
Desc: Texture sampling
|
||||
#*/
|
||||
/*#
|
||||
Func: TextureSetWrapping
|
||||
Proto: void:Texture,bool wrap_u, bool wrap_v
|
||||
Desc: Set the texture U and V wrap modes.
|
||||
#*/
|
||||
sq_register(vm, TextureSetWrapping, "TextureSetWrapping", _SC(".xbb"));
|
||||
|
||||
/*#
|
||||
Section: TextureGeneric
|
||||
Desc: Generic
|
||||
#*/
|
||||
/*#
|
||||
Func: TextureGetWidth
|
||||
Proto: int:texture
|
||||
Desc: Return the texture width.
|
||||
#*/
|
||||
sq_register(vm, TextureGetWidth, "TextureGetWidth", _SC(".x"));
|
||||
/*#
|
||||
Func: TextureGetHeight
|
||||
Proto: int:texture
|
||||
Desc: Return the texture height.
|
||||
#*/
|
||||
sq_register(vm, TextureGetHeight, "TextureGetHeight", _SC(".x"));
|
||||
|
||||
/*#
|
||||
Func: TextureUpdate
|
||||
Proto: bool:Texture,Picture
|
||||
Desc: Update the texture data from a picture object.
|
||||
#*/
|
||||
sq_register(vm, TextureUpdate, "TextureUpdate", _SC(".xx"));
|
||||
/*#
|
||||
Func: TextureRelease
|
||||
Proto: void:Texture
|
||||
Desc: Release the renderer data for a given texture. A subsequent call to TextureUpdate will then recreate the renderer object.
|
||||
#*/
|
||||
sq_register(vm, TextureRelease, "TextureRelease", _SC(".x"));
|
||||
|
||||
sq_pushroottable(vm);
|
||||
|
||||
/*#
|
||||
Enum: StreamState
|
||||
Values: StreamPlaying,StreamPaused
|
||||
#*/
|
||||
#if __ENABLE_DAV__
|
||||
sq_pushstring(vm, "StreamPlaying", -1); sq_pushinteger(vm, TextureStreamInterface::Stream_Playing); sq_newslot(vm, -3, true);
|
||||
sq_pushstring(vm, "StreamPaused", -1); sq_pushinteger(vm, TextureStreamInterface::Stream_Paused); sq_newslot(vm, -3, true);
|
||||
#endif
|
||||
|
||||
sq_pushstring(vm, "NullTexture", -1); CObject::Push(vm, NULL, typetag_Texture); sq_newslot(vm, -3, true);
|
||||
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
84
include/modules/script_squirrel/legacy/trigger_binding.cpp
Normal file
84
include/modules/script_squirrel/legacy/trigger_binding.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "binding_helpers.h"
|
||||
#include "scene3d/mtrigger.h"
|
||||
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SQInteger TriggerGetItemList(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSINGLESAFEPTR(t, MTrigger, typetag_Trigger)
|
||||
sq_newarray(vm, 0);
|
||||
ListForeachPtr(Trigger::ItemInTrigger *, i, t->items_in_trigger)
|
||||
if (i->inside)
|
||||
{
|
||||
CObject::Push(vm, (void *)i, typetag_Item);
|
||||
sq_arrayappend(vm, -2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
SQInteger TriggerTestItem(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(t, MTrigger, typetag_Trigger)
|
||||
__SQ_GETSAFEPTR(i, MItem, typetag_Item)
|
||||
__SQ_GETEND
|
||||
|
||||
ListForeachPtr(Trigger::ItemInTrigger *, _i, t->items_in_trigger)
|
||||
if (_i->inside && (i == (MItem *)_i->item->mitem))
|
||||
__SQ_RETURNBOOL(true)
|
||||
|
||||
__SQ_RETURNBOOL(false)
|
||||
}
|
||||
SQInteger TriggerPosInside(HSQUIRRELVM vm)
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(t, MTrigger, typetag_Trigger)
|
||||
__SQ_GETVECTOR(p)
|
||||
__SQ_GETEND
|
||||
|
||||
__SQ_RETURNBOOL(t->IsInside(p))
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void RegisterTriggerBinding(HSQUIRRELVM vm)
|
||||
{
|
||||
/*#
|
||||
Topic: Trigger
|
||||
Type: Trigger
|
||||
Related: Item
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: TriggerGeneral
|
||||
Desc: Trigger general functions.
|
||||
#*/
|
||||
/*#
|
||||
Func: TriggerGetItemList
|
||||
Proto: array:Item
|
||||
Desc: Return an array of items currently inside this trigger.
|
||||
#*/
|
||||
sq_register(vm, TriggerGetItemList, "TriggerGetItemList", _SC(".x"));
|
||||
/*#
|
||||
Func: TriggerTestItem
|
||||
Proto: bool:Item trigger,Item item
|
||||
Desc: Test if a given item is currently inside this trigger.
|
||||
#*/
|
||||
sq_register(vm, TriggerTestItem, "TriggerTestItem", _SC(".xx"));
|
||||
/*#
|
||||
Func: TriggerPosInside
|
||||
Proto: bool:Item trigger,Vector p
|
||||
Desc: Test if a given p is currently inside this trigger.
|
||||
#*/
|
||||
sq_register(vm, TriggerPosInside, "TriggerPosInside", _SC(".xx"));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
2639
include/modules/script_squirrel/legacy/ui_binding.cpp
Normal file
2639
include/modules/script_squirrel/legacy/ui_binding.cpp
Normal file
File diff suppressed because it is too large
Load Diff
644
include/modules/script_squirrel/legacy/wii_binding.cpp
Normal file
644
include/modules/script_squirrel/legacy/wii_binding.cpp
Normal file
@ -0,0 +1,644 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#if __PLATFORM_NINTENDO_WII__
|
||||
|
||||
|
||||
#include "squirrel_binding.h"
|
||||
#include "binding_helpers.h"
|
||||
#include "uc_binding.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <Revolution.h>
|
||||
#include <revolution/kpad.h>
|
||||
#include <revolution/sc.h>
|
||||
#include <revolution/arc.h>
|
||||
#include <revolution/cx.h>
|
||||
#include <revolution/tmcc/tmcc_jpeg.h>
|
||||
|
||||
#include <revolution/sc.h>
|
||||
#include <revolution/os.h>
|
||||
#include <revolution/mem/allocator.h>
|
||||
#include <revolution/wpad.h>
|
||||
|
||||
#include "Wii_platform.h"
|
||||
|
||||
//---------------------------------------------------------
|
||||
WIIHome Wii::HomeMenu ATTRIBUTE_ALIGN(32);
|
||||
|
||||
nWiiMixer* Wii::Mixer = NULL;
|
||||
WiiSaveMngr Wii::Save;
|
||||
nWiiGXRenderer* Wii::Renderer = NULL;
|
||||
GSFramework* Wii::Engine = NULL;
|
||||
nProject* Wii::Project = NULL;
|
||||
WIIWareStrap* Wii::Strap = NULL;
|
||||
nWiiAllocator Wii::MEM2_allocator;
|
||||
nIOMemoryFS* Wii::pMemory_fs = NULL;
|
||||
|
||||
unsigned int Wii::LastAudioUpdateTime = (u32)OSGetTick();
|
||||
bool Wii::DisableAudioUpdate = false;
|
||||
bool Wii::VideoInited = false;
|
||||
//---------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------
|
||||
bool Wii::LoadingAudioUpdate()
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
#define WII_LOADING_AUDIO_UPDATE_PERIOD_MS (1000/20)
|
||||
#define WII_LOADING_AUDIO_UPDATE_SLEEP_MS (2)
|
||||
|
||||
if (DisableAudioUpdate)
|
||||
return;
|
||||
|
||||
u32 currentTick = (u32)OSGetTick();
|
||||
u32 diffCSTime = OSTicksToMilliseconds( OSDiffTick( currentTick, LastAudioUpdateTime ) );
|
||||
|
||||
if (diffCSTime >= WII_LOADING_AUDIO_UPDATE_PERIOD_MS)
|
||||
{
|
||||
if (Wii::Mixer)
|
||||
{
|
||||
Wii::Mixer->Update();
|
||||
OSSleepMilliseconds( WII_LOADING_AUDIO_UPDATE_SLEEP_MS );
|
||||
|
||||
// OSReport("audio updated, delayMs=%d\n",diffCSTime);
|
||||
}
|
||||
LastAudioUpdateTime = (u32)OSGetTick();
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
void Wii::EnableHomeMenu(bool value)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
if (value)
|
||||
WIIHome::enableFlags &= ~WII_HOME_DISABLE_HOME_BUTTON;
|
||||
else
|
||||
WIIHome::enableFlags |= WII_HOME_DISABLE_HOME_BUTTON;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
void Wii::ForceReturnToMenuInsteadOfReset(bool value)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
WIIHome::forceReturnToMenuInsteadOfReset = value;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
bool Wii::EnableResetAndPowerButtons(bool enable, bool allowPostpone)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
u32 f = WII_HOME_DISABLE_RESET_BUTTON | WII_HOME_DISABLE_POWER_BUTTON;
|
||||
bool res = !(WIIHome::enableFlags & f);
|
||||
|
||||
if (!enable && allowPostpone)
|
||||
f |= WII_HOME_ALLOW_POWER_POSTPONE | WII_HOME_ALLOW_RESET_POSTPONE;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
WIIHome::enableFlags &= ~f;
|
||||
WIIHome::enableFlags &= ~WII_HOME_ALLOW_POWER_POSTPONE;
|
||||
WIIHome::enableFlags &= ~WII_HOME_ALLOW_RESET_POSTPONE;
|
||||
}
|
||||
else
|
||||
WIIHome::enableFlags |= f;
|
||||
return res;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
float Wii::GetSquareRatioFor16_9()
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
// cf VI_library_book, page 47
|
||||
// Game Virtual Space EFB XFB VI
|
||||
//NTSC, EURGB60 832<33>456 640<34>456 640<34>456 686<38>456
|
||||
//PAL 832<33>456 640<34>456 640<34>542 682<38>542
|
||||
|
||||
if (SCGetAspectRatio()!=SC_ASPECT_RATIO_16x9) {
|
||||
return(1.0f);
|
||||
}
|
||||
else {
|
||||
if ( (SCGetEuRgb60Mode() == SC_EURGB60_MODE_ON)
|
||||
|| (VIGetTvFormat() != VI_PAL)) {
|
||||
return(686.0f/832.0f);
|
||||
}
|
||||
else {
|
||||
return(682.0f/832.0f);
|
||||
}
|
||||
}
|
||||
|
||||
return (1.0f);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiStartHomeMenu(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
if ( !Wii::HomeMenu.IsActivated()
|
||||
&& ((Wii::HomeMenu.enableFlags & WII_HOME_DISABLE_HOME_BUTTON)==0)) {
|
||||
Wii::HomeMenu.Init( SCGetAspectRatio()==SC_ASPECT_RATIO_16x9, VIGetTvFormat() );
|
||||
}
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiEnableHomeMenu(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETBOOL(value)
|
||||
__SQ_GETEND
|
||||
Wii::EnableHomeMenu(value);
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiGetHomeMenuRunning(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_RETURNBOOL(Wii::HomeMenu.IsActivated() == 1)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiEnableResetAndPowerButtons(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETBOOL(value)
|
||||
__SQ_GETEND
|
||||
Wii::EnableResetAndPowerButtons(value);
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiIs16_9(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_RETURNBOOL(SCGetAspectRatio()==SC_ASPECT_RATIO_16x9)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiGetSquareRatioFor16_9(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_RETURNFLOAT(Wii::GetSquareRatioFor16_9());
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiReturnToDataManager(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
WIIHome::PowerAndResetPreprocess();
|
||||
OSReturnToDataManager();
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiInitStrap(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
if (Wii::Strap) {
|
||||
static const GXColor fg = {0x00, 0xff, 0xff, 0xff};
|
||||
static const GXColor bg = {0x00, 0x00, 0x00, 0x00};
|
||||
OSFatal ( fg, bg, "WiiInitStrap" );
|
||||
}
|
||||
Wii::Strap = new WIIWareStrap();
|
||||
Wii::Strap->Init();
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
extern GSFramework *gEngine;
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiDeInitStrap(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
if (Wii::Strap) {
|
||||
Wii::Strap->DeInit();
|
||||
delete Wii::Strap;
|
||||
Wii::Strap = NULL;
|
||||
|
||||
// a quoi servait ce code d<>ja ???
|
||||
// VISetBlack(TRUE);
|
||||
// for (s32 i=0;i<2;i++) {
|
||||
// gEngine->GetRenderer()->ShowFrame();
|
||||
// VIWaitForRetrace();
|
||||
// }
|
||||
// VISetBlack(FALSE);
|
||||
// VIWaitForRetrace();
|
||||
}
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiDrawStrap(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
Wii::Strap->Draw();
|
||||
VIWaitForRetrace();
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiGetVersion(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
static const char noe[] = "NOE";
|
||||
static const char noa[] = "NOA";
|
||||
__SQ_RETURNSTRING ((WiiErrorMngr::Version == WiiErrorMngr::VERSION_NOE) ? noe : noa);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiGetLastErrorStrId(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_RETURNSTRING (WiiErrorMngr::GetLastErrorStrId().c_str());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiGetLastErrorText(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_RETURNSTRING (WiiErrorMngr::GetLastErrorText(WiiErrorMngr::ForcedLocaleForGetLastErrorText).c_str());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiGetOptionText(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(optionStrID)
|
||||
const char* res = ((WiiErrorMngr::GetOptionText(optionStrID, WiiErrorMngr::ForcedLocaleForGetLastErrorText)).c_str());
|
||||
__SQ_GETEND
|
||||
|
||||
__SQ_RETURNSTRING(res);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiSetGameTitle(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETSTRING(title)
|
||||
WiiErrorMngr::SetGameTitle(title);
|
||||
__SQ_GETEND
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiSaveInit(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETINT(nbMetafiles)
|
||||
__SQ_GETINT(saveSizeInBytes)
|
||||
__SQ_GETINT(saveIconNbPictures)
|
||||
__SQ_GETEND
|
||||
|
||||
WiiSaveMngr::Init(nbMetafiles, saveSizeInBytes, saveIconNbPictures);
|
||||
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiSaveExists(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_RETURNBOOL (WiiSaveMngr::SaveFileExists());
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiSaveSave(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
// #define DEBUG_RESET_WHILE_SAVING
|
||||
// #define DEBUG_POWER_WHILE_SAVING
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_RESET_WHILE_SAVING
|
||||
WIIHome::reset_called = true;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_POWER_WHILE_SAVING
|
||||
WIIHome::power_called = true;
|
||||
#endif
|
||||
|
||||
WiiSaveMngr::Save();
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
/*
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiSaveLoad(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
// WiiSaveMngr::Save();
|
||||
__SQ_RETURN
|
||||
}
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiSaveSetMetafile(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(2)
|
||||
__SQ_GETSAFEPTR(metafile, nMetaFile, typetag_Metafile)
|
||||
__SQ_GETINT(id)
|
||||
WiiSaveMngr::SetMetafile(metafile, id);
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiSaveGetMetafile(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETINT(id)
|
||||
nMetaFile* ptr = WiiSaveMngr::GetMetafile(id);
|
||||
__SQ_RETURNMANAGEDSAFEPTR(ptr, typetag_Metafile)
|
||||
__SQ_GETEND
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiSaveDelete(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
WiiSaveMngr::DeleteSaveFile();
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiGameRestart(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
Wii::HomeMenu.PerformReset();
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiDumpMemInfo(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
#if __ENABLE_ENGINE_LOG__
|
||||
u32 freeMem1 = MEMGetTotalFreeSizeForExpHeap(((nWiiAllocator *)MEM1_allocator.vacc)->heap);
|
||||
OSReport("Mem1 Free = %do, %.2fko, %.2fMo\n", freeMem1, freeMem1/1024.0f, freeMem1/(1024.0f*1024.0f));
|
||||
|
||||
u32 freeMem2 = MEMGetTotalFreeSizeForExpHeap(Wii::MEM2_allocator.heap);
|
||||
OSReport("Mem2 Free = %do, %.2fko, %.2fMo\n", freeMem2, freeMem2/1024.0f, freeMem2/(1024.0f*1024.0f));
|
||||
#endif
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiRemoteDisconnect(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(1)
|
||||
__SQ_GETINT(id)
|
||||
|
||||
if (id >= WPAD_CHAN0 && id <= WPAD_CHAN3)
|
||||
WPADDisconnect(id);
|
||||
|
||||
__SQ_RETURN
|
||||
}
|
||||
|
||||
/*
|
||||
//---------------------------------------------------------
|
||||
SQInteger WiiSetClearColor(HSQUIRRELVM vm)
|
||||
//---------------------------------------------------------
|
||||
{
|
||||
__SQ_GETSTART(3)
|
||||
__SQ_GETINT(r)
|
||||
__SQ_GETINT(g)
|
||||
__SQ_GETINT(b)
|
||||
__SQ_GETEND
|
||||
|
||||
GXColor c;
|
||||
c.a = 255;
|
||||
c.r = r;
|
||||
c.g = g;
|
||||
c.b = b;
|
||||
GXSetCopyClear(c, GX_MAX_Z24);
|
||||
|
||||
__SQ_RETURN
|
||||
}
|
||||
*/
|
||||
|
||||
//-------------------------------------------------------
|
||||
void RegisterWiiBinding(HSQUIRRELVM vm)
|
||||
//-------------------------------------------------------
|
||||
{
|
||||
/*#
|
||||
Topic: Wii
|
||||
Desc: NINTENDO Wii specific binding
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Section: WiiHome
|
||||
Desc: Wii Home menu
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Func: WiiEnableHomeMenu
|
||||
Proto: void:bool
|
||||
Desc: Enable or disables the home button.
|
||||
#*/
|
||||
sq_register(vm, WiiEnableHomeMenu, "WiiEnableHomeMenu", _SC(".b"));
|
||||
/*#
|
||||
Func: WiiGetHomeMenuRunning
|
||||
Proto: bool:void
|
||||
Desc: Returns the state of the Home menu.
|
||||
#*/
|
||||
sq_register(vm, WiiGetHomeMenuRunning, "WiiGetHomeMenuRunning", _SC("."));
|
||||
/*#
|
||||
Func: WiiStartHomeMenu
|
||||
Proto: void:void
|
||||
Desc: Launches Home menu (only if it is enabled).
|
||||
#*/
|
||||
sq_register(vm, WiiStartHomeMenu, "WiiStartHomeMenu", _SC("."));
|
||||
/*#
|
||||
Func: WiiReturnToDataManager
|
||||
Proto: void:void
|
||||
Desc: Launches the Home menu (only if it is enabled).
|
||||
#*/
|
||||
sq_register(vm, WiiReturnToDataManager, "WiiReturnToDataManager", _SC("."));
|
||||
|
||||
/*#
|
||||
Section: WiiStrap
|
||||
Desc: Wii strap screen functions
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Func: WiiInitStrap
|
||||
Proto: void:void
|
||||
Desc: Initializes strap screen data.
|
||||
#*/
|
||||
sq_register(vm, WiiInitStrap, "WiiInitStrap", _SC("."));
|
||||
|
||||
/*#
|
||||
Func: WiiDeInitStrap
|
||||
Proto: void:void
|
||||
Desc: Uninitialize strap screen data.
|
||||
#*/
|
||||
sq_register(vm, WiiDeInitStrap, "WiiDeInitStrap", _SC("."));
|
||||
|
||||
/*#
|
||||
Func: WiiDrawStrap
|
||||
Proto: void:void
|
||||
Desc: Draws strap screen data.
|
||||
#*/
|
||||
sq_register(vm, WiiDrawStrap, "WiiDrawStrap", _SC("."));
|
||||
|
||||
/*#
|
||||
Section: WiiSystem
|
||||
Desc: Wii system functions
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Func: WiiEnableResetButton
|
||||
Proto: void:bool
|
||||
Desc: Enable or disables the reset/shutdown button.
|
||||
#*/
|
||||
sq_register(vm, WiiEnableResetAndPowerButtons, "WiiEnableResetAndPowerButtons", _SC(".b"));
|
||||
|
||||
/*#
|
||||
Func: WiiIs16_9
|
||||
Proto: bool:void
|
||||
Desc: Returns true if the Wii system configuration is set to 16/9 mode.
|
||||
#*/
|
||||
sq_register(vm, WiiIs16_9, "WiiIs16_9", _SC("."));
|
||||
|
||||
/*#
|
||||
Func: WiiGetSquareRatioFor16_9
|
||||
Proto: float:void
|
||||
Desc: Returns the ratio to use to scale 2D images in order to have square pixels on any TV screen.
|
||||
#*/
|
||||
sq_register(vm, WiiGetSquareRatioFor16_9, "WiiGetSquareRatioFor16_9", _SC("."));
|
||||
|
||||
/*#
|
||||
Func: WiiGetVersion
|
||||
Proto: String:void
|
||||
Desc: Returns "NOE" (Europe) or "NOA" (America).
|
||||
#*/
|
||||
sq_register(vm, WiiGetVersion, "WiiGetVersion", _SC("."));
|
||||
|
||||
/*#
|
||||
Func: WiiGetLastErrorStrId
|
||||
Proto: String:void
|
||||
Desc: Returns ID of the last error, returns an empty string if none.
|
||||
#*/
|
||||
sq_register(vm, WiiGetLastErrorStrId, "WiiGetLastErrorStrId", _SC("."));
|
||||
|
||||
/*#
|
||||
Func: WiiGetLastErrorText
|
||||
Proto: String:void
|
||||
Desc: Returns a localized string describing last error.
|
||||
#*/
|
||||
sq_register(vm, WiiGetLastErrorText, "WiiGetLastErrorText", _SC("."));
|
||||
|
||||
/*#
|
||||
Func: WiiGetOptionText
|
||||
Proto: String:String error_id
|
||||
Desc: Returns a localized string describing a non blocking error option string ID.
|
||||
#*/
|
||||
sq_register(vm, WiiGetOptionText, "WiiGetOptionText", _SC(".s"));
|
||||
|
||||
/*#
|
||||
Func: WiiSetGameTitle
|
||||
Proto: void:String title
|
||||
Desc: Sets the game title that may be displayed in Wii error screens
|
||||
#*/
|
||||
sq_register(vm, WiiSetGameTitle, "WiiSetGameTitle", _SC(".s"));
|
||||
|
||||
/*#
|
||||
Section: WiiSave
|
||||
Desc: Wii save system functions
|
||||
#*/
|
||||
|
||||
/*#
|
||||
Func: WiiSaveInit
|
||||
Proto: void:int nbMetafiles, int saveSizeInBytes, int saveIconNbPictures
|
||||
Desc: Initialize the Wii save system information (does not perform any read/write to NAND).
|
||||
#*/
|
||||
sq_register(vm, WiiSaveInit, "WiiSaveInit", _SC(".iii"));
|
||||
/*#
|
||||
Func: WiiSaveExists
|
||||
Proto: bool:void
|
||||
Desc: Returns TRUE if save data exists (does not perform any write to NAND).
|
||||
#*/
|
||||
sq_register(vm, WiiSaveExists, "WiiSaveExists", _SC("."));
|
||||
/*#
|
||||
Func: WiiSaveSave
|
||||
Proto: void:void
|
||||
Desc: Saves data to the Wii NAND memory (WiiSaveInit / WiiSaveAddMetafile must have been called before calling this function).
|
||||
#*/
|
||||
sq_register(vm, WiiSaveSave, "WiiSaveSave", _SC("."));
|
||||
|
||||
/*#
|
||||
Func: WiiSaveLoad
|
||||
Proto: void:void
|
||||
Desc: TBD (WiiSaveInit / WiiSaveSetMetafile must have been called before calling this function).
|
||||
#*/
|
||||
// sq_register(vm, WiiSaveLoad, "WiiSaveLoad", _SC("."));
|
||||
|
||||
/*#
|
||||
Func: WiiSaveSetMetafile
|
||||
Proto: void:Metafile,int id
|
||||
Desc: TBD
|
||||
#*/
|
||||
sq_register(vm, WiiSaveSetMetafile, "WiiSaveSetMetafile", _SC(".xi"));
|
||||
|
||||
/*#
|
||||
Func: WiiSaveGetMetafile
|
||||
Proto: Metafile:int id
|
||||
Desc: TBD
|
||||
#*/
|
||||
sq_register(vm, WiiSaveGetMetafile, "WiiSaveGetMetafile", _SC(".i"));
|
||||
|
||||
/*#
|
||||
Func: WiiSaveDelete
|
||||
Proto: void:void
|
||||
Desc: deletes a game save data & save banner
|
||||
#*/
|
||||
sq_register(vm, WiiSaveDelete, "WiiSaveDelete", _SC("."));
|
||||
|
||||
/*#
|
||||
Func: WiiGameRestart
|
||||
Proto: void:void
|
||||
Desc: restarts the game (like pressing reset ...)
|
||||
#*/
|
||||
sq_register(vm, WiiGameRestart, "WiiGameRestart", _SC("."));
|
||||
|
||||
/*
|
||||
Func: WiiSetClearColor
|
||||
Proto: void:int r,int g,int b
|
||||
Desc: changes the wii clear color
|
||||
*/
|
||||
//sq_register(vm, WiiSetClearColor, "WiiSetClearColor", _SC(".iii"));
|
||||
|
||||
/*#
|
||||
Func: WiiDumpMemInfo
|
||||
Proto: void:void
|
||||
Desc: TBD
|
||||
#*/
|
||||
sq_register(vm, WiiDumpMemInfo, "WiiDumpMemInfo", _SC("."));
|
||||
|
||||
/*#
|
||||
Func: WiiRemoteDisconnect
|
||||
Proto: void:int id
|
||||
Desc: TBD
|
||||
#*/
|
||||
sq_register(vm, WiiRemoteDisconnect, "WiiRemoteDisconnect", _SC(".i"));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
48
include/modules/script_squirrel/mmf.cpp
Normal file
48
include/modules/script_squirrel/mmf.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include "mmf.h"
|
||||
|
||||
/**
|
||||
*/
|
||||
CMMF::CMMF(LPCTSTR MMFName, int size, LPCTSTR mutexName) :
|
||||
m_nSize(size),
|
||||
m_hMutex(0)
|
||||
{
|
||||
m_hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, m_nSize, MMFName);
|
||||
m_pSharedData = MapViewOfFile(m_hFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
|
||||
|
||||
if(mutexName != NULL)
|
||||
m_hMutex = CreateMutex(NULL, FALSE, mutexName);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
CMMF::~CMMF(void)
|
||||
{
|
||||
UnmapViewOfFile(m_pSharedData);
|
||||
CloseHandle(m_hFileMapping);
|
||||
|
||||
if(m_hMutex)
|
||||
CloseHandle(m_hMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the current contents of the MMF into pData (buffer must be big enough to receive m_nSize bytes).
|
||||
* Waits for locked mutex to be released if mutex name was specified during construction.
|
||||
*/
|
||||
void CMMF::Read(void* pData, bool read /* = TRUE */)
|
||||
{
|
||||
if(m_hMutex)
|
||||
WaitForSingleObject(m_hMutex, INFINITE);
|
||||
|
||||
memcpy(read ? pData : m_pSharedData, read ? m_pSharedData : pData, m_nSize);
|
||||
|
||||
if(m_hMutex)
|
||||
ReleaseMutex( m_hMutex );
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the contents of pData into the MMF, waiting for the MMF lock to be released if applicable.
|
||||
*/
|
||||
void CMMF::Write(void* pData)
|
||||
{
|
||||
Read(pData, false);
|
||||
}
|
||||
266
include/modules/script_squirrel/squirrel_analyzer.cpp
Normal file
266
include/modules/script_squirrel/squirrel_analyzer.cpp
Normal file
@ -0,0 +1,266 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "script_squirrel/squirrel_analyzer.h"
|
||||
#include "ascii/parser.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "platform.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::SquirrelAnalyzer;
|
||||
using namespace GS::AsciiParser;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/* static bool SymbolFindByNameFunctor(Symbol *s, const char *n) { return s->name == n; } */
|
||||
static bool SourceFindByNameFunctor(Source *s, const char *n) { return s->name == n; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct ParserContext
|
||||
{
|
||||
const char *s, *e, *o;
|
||||
SharedList <Symbol *> *symbols;
|
||||
Symbol::Type type;
|
||||
|
||||
Offset CurrentOffset() const
|
||||
{
|
||||
Offset offset(1, 0);
|
||||
for (const char *p = o; p < e; ++offset.line)
|
||||
{
|
||||
const char *eol = RunToEOL(p, e);
|
||||
|
||||
if (eol > s)
|
||||
{
|
||||
offset.column = s - p;
|
||||
break;
|
||||
}
|
||||
if (eol >= e)
|
||||
return Offset(1, 0);
|
||||
|
||||
p = SkipEOL(eol, e);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
ParserContext(const char *_s, const char *_e, const char *_o, SharedList <Symbol *> *_symbols, Symbol::Type _type) : s(_s), e(_e), o(_o), symbols(_symbols), type(_type) {}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ParseContext(ParserContext &);
|
||||
bool ParseMemberVariable(ParserContext &ctx)
|
||||
{
|
||||
AutoPtr <Variable> _var(new Variable);
|
||||
_var->offset = ctx.CurrentOffset();
|
||||
_var->var_type = Variable::VarMember;
|
||||
|
||||
const char *e = SkipEntry(ctx.s, ctx.e);
|
||||
_var->name.Set(ctx.s, e);
|
||||
|
||||
ctx.s = NextEntry(ctx.s, ctx.e) + 1;
|
||||
ctx.symbols->Add(_var.Detach());
|
||||
return true;
|
||||
}
|
||||
bool ParseGlobalVariable(ParserContext &ctx)
|
||||
{
|
||||
AutoPtr <Variable> _var(new Variable);
|
||||
_var->offset = ctx.CurrentOffset();
|
||||
_var->var_type = Variable::VarGlobal;
|
||||
|
||||
const char *e = SkipEntry(ctx.s, ctx.e);
|
||||
_var->name.Set(ctx.s, e);
|
||||
|
||||
ctx.s = NextEntry(ctx.s, ctx.e) + 2;
|
||||
ctx.symbols->Add(_var.Detach());
|
||||
return true;
|
||||
}
|
||||
bool ParseLocalVariable(ParserContext &ctx)
|
||||
{
|
||||
AutoPtr <Variable> _var(new Variable);
|
||||
_var->offset = ctx.CurrentOffset();
|
||||
_var->var_type = Variable::VarLocal;
|
||||
|
||||
const char *s = NextEntry(ctx.s, ctx.e);
|
||||
_var->name.Set(s, SkipEntry(s, ctx.e));
|
||||
ctx.symbols->Add(_var.Detach());
|
||||
|
||||
// parse subsequent declarations.
|
||||
s = NextEntry(s, ctx.e);
|
||||
|
||||
forever
|
||||
{
|
||||
/*
|
||||
// TODO a naive test won't do as there is no mandatory end-of-statement in Squirrel
|
||||
if (s[0] == '=')
|
||||
{
|
||||
// check if there are more variables declared by this statement
|
||||
}
|
||||
*/
|
||||
if (s[0] == ',')
|
||||
{
|
||||
s = NextEntry(s + 1, ctx.e);
|
||||
ctx.s = s;
|
||||
|
||||
_var = new Variable;
|
||||
_var->offset = ctx.CurrentOffset();
|
||||
_var->var_type = Variable::VarLocal;
|
||||
|
||||
_var->name.Set(s, SkipEntry(s, ctx.e));
|
||||
ctx.symbols->Add(_var.Detach());
|
||||
|
||||
s = NextEntry(s, ctx.e);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
ctx.s = s;
|
||||
return true;
|
||||
}
|
||||
bool ParseFunction(ParserContext &ctx)
|
||||
{
|
||||
AutoPtr <Function> _function(new Function);
|
||||
_function->offset = ctx.CurrentOffset();
|
||||
|
||||
const char *s = NextEntry(ctx.s, ctx.e);
|
||||
_function->name.Set(s, SkipEntry(s, ctx.e));
|
||||
|
||||
s = NextEntry(s, ctx.e);
|
||||
|
||||
// Parse prototype.
|
||||
if (s[0] != '(')
|
||||
return false;
|
||||
|
||||
const char *eoproto = RunToEOG(s, ctx.e, '(', ')');
|
||||
if (eoproto == NULL)
|
||||
return false;
|
||||
|
||||
_function->prototype.Set(s + 1, eoproto);
|
||||
s = NextEntry(eoproto + 1, ctx.e);
|
||||
|
||||
// Parse function content.
|
||||
if (s[0] != '{')
|
||||
return false;
|
||||
|
||||
const char *eofunc = RunToEOG(s, ctx.e, '{', '}');
|
||||
if (eofunc == NULL)
|
||||
eofunc = ctx.e;
|
||||
ParserContext func_ctx(s + 1, eofunc, ctx.o, &_function->symbols, _function->type);
|
||||
|
||||
ParseContext(func_ctx);
|
||||
|
||||
ctx.s = eofunc + 1;
|
||||
ctx.symbols->Add(_function.Detach());
|
||||
return true;
|
||||
}
|
||||
bool ParseClass(ParserContext &ctx)
|
||||
{
|
||||
AutoPtr <Class> _class(new Class);
|
||||
_class->offset = ctx.CurrentOffset();
|
||||
|
||||
ctx.s = NextEntry(ctx.s, ctx.e);
|
||||
_class->name.Set(ctx.s, SkipEntry(ctx.s, ctx.e));
|
||||
|
||||
const char *s = NextEntry(ctx.s, ctx.e);
|
||||
|
||||
if (!String::strccmp("extends", s))
|
||||
{
|
||||
s = NextEntry(s, ctx.e);
|
||||
_class->extends.Set(s, SkipEntry(s, ctx.e));
|
||||
|
||||
ctx.s = SkipEntry(s, ctx.e);
|
||||
|
||||
s = NextEntry(s, ctx.e);
|
||||
if (s == ctx.e)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse class content.
|
||||
if (s[0] != '{')
|
||||
return false;
|
||||
|
||||
const char *eoclass = RunToEOG(s, ctx.e, '{', '}');
|
||||
if (eoclass == NULL)
|
||||
eoclass = ctx.e;
|
||||
|
||||
ParserContext class_ctx(s + 1, eoclass, ctx.o, &_class->symbols, _class->type);
|
||||
ParseContext(class_ctx);
|
||||
|
||||
ctx.s = eoclass + 1;
|
||||
ctx.symbols->Add(_class.Detach());
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ParseContext(ParserContext &ctx)
|
||||
{
|
||||
for (bool r = true; r && (ctx.s < ctx.e); )
|
||||
{
|
||||
if (!String::strccmp("class", ctx.s))
|
||||
r = ParseClass(ctx);
|
||||
else if (!String::strccmp("function", ctx.s))
|
||||
r = ParseFunction(ctx);
|
||||
else if (!String::strccmp("local", ctx.s))
|
||||
r = ParseLocalVariable(ctx);
|
||||
else
|
||||
{
|
||||
const char *e = SkipEntry(ctx.s, ctx.e);
|
||||
String tmp(ctx.s, e);
|
||||
|
||||
const char *s = NextEntry(ctx.s, ctx.e);
|
||||
if (ctx.s == s)
|
||||
++ctx.s; // skip
|
||||
else
|
||||
{
|
||||
if ((s[0] == '<') && (s[1] == '-'))
|
||||
r = ParseGlobalVariable(ctx);
|
||||
else if ((ctx.type == Symbol::TypeClass) && (s[0] == '='))
|
||||
r = ParseMemberVariable(ctx);
|
||||
else
|
||||
ctx.s = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Source *ParseSource(const char *s, const char *e)
|
||||
{
|
||||
AutoPtr <Source> source(new Source);
|
||||
|
||||
ParserContext ctx(s, e, s, &source->symbols, Symbol::TypeNone);
|
||||
ParseContext(ctx);
|
||||
|
||||
return source.Detach();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Source *SquirrelAnalyzer::Analyze(const char *nut, Program &program, bool replace)
|
||||
{
|
||||
Source *old_source = ListFindEx(program.sources, SourceFindByNameFunctor, nut);
|
||||
if (old_source && !replace)
|
||||
return NULL;
|
||||
|
||||
String source;
|
||||
{
|
||||
Array <char> buffer;
|
||||
if (!Platform::Get().io->FileLoad(nut, buffer))
|
||||
return NULL;
|
||||
source.Set(buffer.c_ptr(), buffer.c_ptr() + buffer.GetCount());
|
||||
}
|
||||
|
||||
Source *new_source = ParseSource(source.c_str(), source.c_str() + source.Len());
|
||||
if (!new_source)
|
||||
return NULL;
|
||||
|
||||
new_source->name = nut;
|
||||
|
||||
program.sources.Remove(old_source);
|
||||
program.sources.Add(new_source);
|
||||
return new_source;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
88
include/modules/script_squirrel/squirrel_analyzer_debug.cpp
Normal file
88
include/modules/script_squirrel/squirrel_analyzer_debug.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "script_squirrel/squirrel_analyzer.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::SquirrelAnalyzer;
|
||||
|
||||
|
||||
void DumpSymbols(const SharedList <Symbol *> &, int);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void DumpSymbol(const Symbol *symbol, int tab)
|
||||
{
|
||||
for (int n = 0; n < tab; ++n)
|
||||
__LOG__ << " ";
|
||||
|
||||
__LOG__ << "offset: line " << symbol->offset.line << ", column " << symbol->offset.column << " -> ";
|
||||
|
||||
switch (symbol->type)
|
||||
{
|
||||
case Symbol::TypeClass:
|
||||
if (Class *c = (Class *)symbol)
|
||||
{
|
||||
__LOG__ << "Class " << c->name;
|
||||
if (!c->extends.IsEmpty())
|
||||
__LOG__ << " extends: " << c->extends << "\n";
|
||||
__LOG__ << "\n";
|
||||
|
||||
DumpSymbols(c->symbols, tab + 4);
|
||||
}
|
||||
break;
|
||||
|
||||
case Symbol::TypeFunction:
|
||||
if (Function *f = (Function *)symbol)
|
||||
{
|
||||
__LOG__ << "Function " << f->name << "(" << f->prototype << ")\n";
|
||||
DumpSymbols(f->symbols, tab + 4);
|
||||
}
|
||||
break;
|
||||
|
||||
case Symbol::TypeVariable:
|
||||
if (Variable *v = (Variable *)symbol)
|
||||
switch (v->var_type)
|
||||
{
|
||||
case Variable::VarLocal: __LOG__ << "Local variable " << v->name << "\n"; break;
|
||||
case Variable::VarGlobal: __LOG__ << "Global variable " << v->name << "\n"; break;
|
||||
case Variable::VarMember: __LOG__ << "Member variable " << v->name << "\n"; break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
__LOG__ << "Variable " << symbol->name << "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
void DumpSymbols(const SharedList <Symbol *> &symbols, int tab)
|
||||
{
|
||||
ListForeachPtr(Symbol *, symbol, symbols)
|
||||
DumpSymbol(symbol, tab);
|
||||
}
|
||||
void DumpSource(const Source *source)
|
||||
{
|
||||
ListForeachPtr(Symbol *, symbol, source->symbols)
|
||||
{
|
||||
switch (symbol->type)
|
||||
{
|
||||
case Symbol::TypeClass: __LOG__ << " Class"; break;
|
||||
case Symbol::TypeFunction: __LOG__ << " Function"; break;
|
||||
case Symbol::TypeVariable: __LOG__ << " Variable"; break;
|
||||
}
|
||||
|
||||
__LOG__ << " '" << symbol->name << "'\n";
|
||||
}
|
||||
}
|
||||
void DumpProgram(const Program &program)
|
||||
{
|
||||
ListForeachPtr(Source *, source, program.sources)
|
||||
{
|
||||
__LOG__ << "Source '" << source->name << "'\n";
|
||||
DumpSymbols(source->symbols, 4);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
398
include/modules/script_squirrel/squirrel_debugger.cpp
Normal file
398
include/modules/script_squirrel/squirrel_debugger.cpp
Normal file
@ -0,0 +1,398 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "script_squirrel/squirrel_debugger.h"
|
||||
#include "script_squirrel/cobject/cobject.h"
|
||||
#include "script_squirrel/cobject/vector_decl.h"
|
||||
#include "math/vector.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
String SquirrelDebugger::FormatParameter(DebuggerVariable *var)
|
||||
{
|
||||
switch (var->type)
|
||||
{
|
||||
case OT_STRING:
|
||||
return String::Format("%s=%s", var->id.c_str(), var->v_string.c_str());
|
||||
case OT_FLOAT:
|
||||
return String::Format("%s=%.4f", var->id.c_str(), var->v_float);
|
||||
case OT_INTEGER:
|
||||
return String::Format("%s=%d", var->id.c_str(), var->v_int);
|
||||
case OT_BOOL:
|
||||
return String::Format("%s=%s", var->id.c_str(), var->v_bool ? "True" : "False");
|
||||
}
|
||||
return var->id;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static int DebuggerCompareVariable(DebuggerVariable *&v, const char *s) { return !String::Compare(v->id, s); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
DebuggerVariable *SquirrelDebugger::InsertVariable(const char *name, AutoList <DebuggerVariable *> &debug_var, int level)
|
||||
{
|
||||
// Catch nesting limit.
|
||||
if (level == 3)
|
||||
return NULL;
|
||||
|
||||
// Try to locate variable in the current watch.
|
||||
DebuggerVariable *var = ListFindEx(debug_var, DebuggerCompareVariable, name);
|
||||
|
||||
// Retrieve stack variable type.
|
||||
bool check_change = false, has_changed = false;
|
||||
|
||||
SQObjectType sq_type = sq_gettype(vm, -1);
|
||||
|
||||
if (var)
|
||||
{
|
||||
// If type has changed, drop the whole member watch structure.
|
||||
if (var->type != (uint)sq_type)
|
||||
var->member_list.Clear();
|
||||
else
|
||||
check_change = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var = new DebuggerVariable;
|
||||
if (!var)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate debugger watch structure.\n", NULL);
|
||||
|
||||
debug_var.Add(var);
|
||||
var->id = name;
|
||||
}
|
||||
|
||||
// Update the variable.
|
||||
var->referenced = true;
|
||||
var->type = sq_type;
|
||||
|
||||
String type = "Unknown", value;
|
||||
int limit = 64 / (level + 1); // Increasingly limit array exploration the deeper in the hierarchy we get.
|
||||
|
||||
switch (sq_type)
|
||||
{
|
||||
case OT_NULL:
|
||||
type = "Null";
|
||||
break;
|
||||
|
||||
case OT_TABLE:
|
||||
{
|
||||
type = "Table";
|
||||
|
||||
// Check item slot.
|
||||
sq_pushnull(vm); // Iterator.
|
||||
while (SQ_SUCCEEDED(sq_next(vm, -2)))
|
||||
{
|
||||
// Here -1 is the value and -2 is the key.
|
||||
const SQChar *slot_name;
|
||||
if (sq_getstring(vm, -2, &slot_name) == SQ_OK)
|
||||
InsertVariable(slot_name, var->member_list, level + 1);
|
||||
|
||||
sq_pop(vm, 2);
|
||||
}
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_ARRAY:
|
||||
{
|
||||
type = "Array";
|
||||
SQInteger array_size = sq_getsize(vm, -1);
|
||||
value = String::Format("{ Length=%d, [...] }", array_size);
|
||||
|
||||
// Check item slot.
|
||||
sq_pushnull(vm); // Iterator.
|
||||
while (SQ_SUCCEEDED(sq_next(vm, -2)))
|
||||
{
|
||||
int idx;
|
||||
sq_getinteger(vm, -2, (SQInteger *)&idx);
|
||||
String slot_name = String::Format("[%d]", idx);
|
||||
InsertVariable(slot_name, var->member_list, level + 1);
|
||||
sq_pop(vm, 2);
|
||||
|
||||
if (--limit == 0)
|
||||
break;
|
||||
}
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_CLOSURE:
|
||||
type = "Function";
|
||||
break;
|
||||
|
||||
case OT_NATIVECLOSURE:
|
||||
type = "C/C++";
|
||||
break;
|
||||
|
||||
case OT_OUTER:
|
||||
type = "Outer";
|
||||
break;
|
||||
|
||||
case OT_USERDATA:
|
||||
type = "User data";
|
||||
break;
|
||||
|
||||
case OT_GENERATOR:
|
||||
type = "Generator";
|
||||
break;
|
||||
|
||||
case OT_USERPOINTER:
|
||||
break;
|
||||
|
||||
case OT_THREAD:
|
||||
type = "Thread";
|
||||
break;
|
||||
|
||||
case OT_FUNCPROTO:
|
||||
type = "Prototype";
|
||||
break;
|
||||
|
||||
case OT_CLASS:
|
||||
type = "Class definition";
|
||||
break;
|
||||
|
||||
case OT_INSTANCE:
|
||||
{
|
||||
type = "Class instance";
|
||||
|
||||
Vector4 *v = NULL;
|
||||
|
||||
CObjectType typetag;
|
||||
if (CObject::GetType(vm, -1, typetag))
|
||||
{
|
||||
type = CObjectTypeToString(typetag);
|
||||
value = FormatUserObjectParameter(typetag);
|
||||
}
|
||||
else if (SQ_SUCCEEDED(sq_getinstanceup(vm, -1, (SQUserPointer*)&v, (SQUserPointer)&__Vector_decl)))
|
||||
{
|
||||
type = "Vector";
|
||||
value = String::Format("{%.2f, %.2f, %.2f, %.2f}", v->x, v->y, v->z, v->w);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Trying iterating over instance members.
|
||||
AutoList <String *> member_list;
|
||||
|
||||
sq_getclass(vm, -1);
|
||||
sq_pushnull(vm); // Iterator.
|
||||
while (SQ_SUCCEEDED(sq_next(vm, -2)))
|
||||
{
|
||||
switch (sq_gettype(vm, -1))
|
||||
{
|
||||
case OT_CLOSURE:
|
||||
case OT_NATIVECLOSURE:
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
const SQChar *slot_name;
|
||||
if (sq_getstring(vm, -2, &slot_name) == SQ_OK)
|
||||
member_list.Add(new String(slot_name));
|
||||
}
|
||||
break;
|
||||
}
|
||||
sq_pop(vm, 2);
|
||||
}
|
||||
sq_pop(vm, 2);
|
||||
|
||||
// Get actual instance values.
|
||||
ListForeachPtr(String *, m, member_list)
|
||||
{
|
||||
sq_pushstring(vm, m->c_str(), m->Len());
|
||||
if (sq_get(vm, -2) == SQ_OK)
|
||||
InsertVariable(m->c_str(), var->member_list, level + 1);
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_WEAKREF:
|
||||
type = "Weakref";
|
||||
break;
|
||||
|
||||
case OT_BOOL:
|
||||
{
|
||||
type = "Bool";
|
||||
SQBool b;
|
||||
sq_getbool(vm, -1, &b);
|
||||
value = b ? "True" : "False";
|
||||
has_changed = check_change ? var->v_bool != asbool(b) : false;
|
||||
var->v_bool = b ? true : false;
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_STRING:
|
||||
{
|
||||
type = "String";
|
||||
const SQChar *s;
|
||||
sq_getstring(vm, -1, &s);
|
||||
value = String::Format("%s", s);
|
||||
has_changed = check_change ? var->v_string != s : false;
|
||||
var->v_string = s;
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_INTEGER:
|
||||
{
|
||||
type = "Integer";
|
||||
SQInteger i;
|
||||
sq_getinteger(vm, -1, &i);
|
||||
value = String::Format("%d", i);
|
||||
has_changed = check_change ? var->v_int != i : false;
|
||||
var->v_int = (int)i;
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_FLOAT:
|
||||
{
|
||||
type = "Float";
|
||||
SQFloat f;
|
||||
sq_getfloat(vm, -1, &f);
|
||||
value = String::Format("%.4f", f);
|
||||
has_changed = check_change ? var->v_float != f : false;
|
||||
var->v_float = f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Value for item with sub-items.
|
||||
if (var->member_list.GetCount() && value.IsEmpty())
|
||||
{
|
||||
value = "{ ";
|
||||
|
||||
int max = 4;
|
||||
ListForeachPtr(DebuggerVariable *, v, var->member_list)
|
||||
{
|
||||
value += max > 0 ? FormatParameter(v).c_str() : "...";
|
||||
value += (iterator.Next() == NULL) || (max == 0) ? " }" : ", ";
|
||||
|
||||
if (!max--)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var->type_string = type;
|
||||
var->modified = has_changed;
|
||||
var->value = value;
|
||||
|
||||
return var;
|
||||
}
|
||||
void SquirrelDebugger::RefreshStackFrameLocalsCache()
|
||||
{
|
||||
// Mark all variables as unreferenced.
|
||||
DereferenceVarTree(local_var_tree);
|
||||
|
||||
// Update local variables.
|
||||
const char *var_name;
|
||||
for (int n = 0; (var_name = sq_getlocal(vm, debug_stack_frame, n)) != NULL; ++n)
|
||||
InsertVariable(var_name, local_var_tree, 0);
|
||||
|
||||
// Drop unreferenced variables.
|
||||
ListForeachPtr(DebuggerVariable *, v, local_var_tree)
|
||||
if (!v->referenced)
|
||||
local_var_tree.Remove(v);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void SquirrelDebugger::VariableToMetatagString(DebuggerVariable *v, String &s)
|
||||
{
|
||||
s += String::Format("<Variable=<Name=\"%s\">\n", v->id.c_str());
|
||||
|
||||
switch (v->type)
|
||||
{
|
||||
case OT_NULL: s += "<ScriptType=\"Null\">\n"; break;
|
||||
case OT_TABLE: s += "<ScriptType=\"Table\">\n"; break;
|
||||
case OT_ARRAY: s += "<ScriptType=\"Array\">\n"; break;
|
||||
case OT_USERDATA: s += "<ScriptType=\"UserData\">\n"; break;
|
||||
case OT_CLOSURE: s += "<ScriptType=\"Closure\">\n"; break;
|
||||
case OT_NATIVECLOSURE: s += "<ScriptType=\"NativeClosure\">\n"; break;
|
||||
case OT_GENERATOR: s += "<ScriptType=\"Generator\">\n"; break;
|
||||
case OT_USERPOINTER: s += "<ScriptType=\"UserPointer\">\n"; break;
|
||||
case OT_THREAD: s += "<ScriptType=\"Thread\">\n"; break;
|
||||
case OT_FUNCPROTO: s += "<ScriptType=\"FuncProto\">\n"; break;
|
||||
case OT_CLASS: s += "<ScriptType=\"Class\">\n"; break;
|
||||
case OT_INSTANCE: s += "<ScriptType=\"Instance\">\n"; break;
|
||||
case OT_WEAKREF: s += "<ScriptType=\"Weakref\">\n"; break;
|
||||
case OT_BOOL: s += "<ScriptType=\"Bool\">\n"; break;
|
||||
case OT_STRING: s += "<ScriptType=\"String\">\n"; break;
|
||||
case OT_INTEGER: s += "<ScriptType=\"Integer\">\n"; break;
|
||||
case OT_FLOAT: s += "<ScriptType=\"Float\">\n"; break;
|
||||
}
|
||||
|
||||
// Display type.
|
||||
s += String::Format("<Type=\"%s\">\n", v->type_string.c_str());
|
||||
|
||||
// Value.
|
||||
if (!v->value.IsEmpty())
|
||||
s += String::Format("<ValueString=\"%s\">\n", v->value.c_str());
|
||||
|
||||
if (v->modified)
|
||||
s += "<Modified>";
|
||||
|
||||
// Members.
|
||||
if (v->member_list.GetCount())
|
||||
{
|
||||
s += "<Members=\n";
|
||||
ListForeachPtr(DebuggerVariable *, m, v->member_list)
|
||||
VariableToMetatagString(m, s);
|
||||
s += ">\n";
|
||||
}
|
||||
|
||||
s += ">\n";
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void SquirrelDebugger::GetStackFrameSource(const char *&source, int &line)
|
||||
{
|
||||
SQStackInfos si;
|
||||
|
||||
if (SQ_SUCCEEDED(sq_stackinfos(vm, debug_stack_frame, &si)))
|
||||
{
|
||||
source = (const char *)si.source;
|
||||
line = si.line;
|
||||
}
|
||||
else
|
||||
{
|
||||
source = NULL;
|
||||
line = -1;
|
||||
}
|
||||
}
|
||||
int SquirrelDebugger::GetStackFrameIndex()
|
||||
{
|
||||
int depth = 0;
|
||||
|
||||
SQStackInfos si;
|
||||
for (int c = 0; SQ_SUCCEEDED(sq_stackinfos(vm, c, &si)); ++c)
|
||||
if (String(si.source) != "NATIVE") // Skip native C frame.
|
||||
{
|
||||
depth = c;
|
||||
break;
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
int SquirrelDebugger::GetCallstackDepth()
|
||||
{
|
||||
int depth = 0;
|
||||
SQStackInfos si;
|
||||
while (SQ_SUCCEEDED(sq_stackinfos(vm, depth, &si)))
|
||||
depth++;
|
||||
return depth;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
SquirrelDebugger::SquirrelDebugger(SquirrelVM &svm)
|
||||
{
|
||||
vm = svm.VM();
|
||||
}
|
||||
522
include/modules/script_squirrel/squirrel_vm.cpp
Normal file
522
include/modules/script_squirrel/squirrel_vm.cpp
Normal file
@ -0,0 +1,522 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <ctime>
|
||||
#include "squirrel.h"
|
||||
#include "sqstdio.h"
|
||||
#include "sqstdmath.h"
|
||||
#include "sqstdstring.h"
|
||||
#include "sqstdaux.h"
|
||||
#include "sqstdblob.h"
|
||||
#include "sqstdsystem.h"
|
||||
#include "script_squirrel/squirrel_vm.h"
|
||||
#include "script_squirrel/cobject/cobject.h"
|
||||
#include "script/script_variant.h"
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "viewer_base/viewer_base.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void SquirrelVM::GetCallStack(AutoList <CallStackEntry *> &callstack)
|
||||
{
|
||||
callstack.Clear();
|
||||
|
||||
SQStackInfos si;
|
||||
for (SQInteger level = 0; SQ_SUCCEEDED(sq_stackinfos(vm, level, &si)); ++level)
|
||||
callstack.Add(new CallStackEntry(si.source, si.funcname, si.line));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void SqPrintFunc(HSQUIRRELVM v, const SQChar *s, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
va_start(arglist, s);
|
||||
char lcl[4096];
|
||||
|
||||
#ifdef __PLATFORM_WINDOWS__
|
||||
vsprintf_s(lcl, 4095, s, arglist);
|
||||
#else
|
||||
vsprintf(lcl, s, arglist);
|
||||
#endif
|
||||
|
||||
__LOG__ << "[S] " << lcl << "\n";
|
||||
va_end(arglist);
|
||||
}
|
||||
static void SqDebugHook(HSQUIRRELVM v, SQInteger type, const SQChar *sourcename, SQInteger line, const SQChar *funcname)
|
||||
{
|
||||
if (SquirrelVM *vm = (SquirrelVM *)sq_getforeignptr(v))
|
||||
if (vm->GetEventHandler())
|
||||
vm->GetEventHandler()->OnStep((char)type, sourcename, line, funcname);
|
||||
}
|
||||
static void SqCompilerError(HSQUIRRELVM v, const SQChar *desc, const SQChar *source, SQInteger line, SQInteger column)
|
||||
{
|
||||
if (SquirrelVM *vm = (SquirrelVM *)sq_getforeignptr(v))
|
||||
{
|
||||
String msg("Script runtime Compilation exception:\n");
|
||||
msg += String::Format(" - (line %d) in \"%s\"\n", line, source);
|
||||
__LOG_E__ << "Squirrel Compiler Error: '" << msg << "'\n\n";
|
||||
|
||||
if (vm->GetEventHandler())
|
||||
vm->GetEventHandler()->OnCompilerError(desc, source, line);
|
||||
|
||||
time_t now = time(NULL);
|
||||
struct tm *timeinfo = localtime(&now);
|
||||
char timestamp[64];
|
||||
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d_%H-%M-%S", timeinfo);
|
||||
|
||||
String logFileName = String::Format("g_engine_log_%s.txt", timestamp);
|
||||
|
||||
// Check if g_engine_log.txt exists and copy it
|
||||
if (Platform::Get().io->Exists("g_engine_log.txt"))
|
||||
{
|
||||
if (Platform::Get().io->FileCopy("g_engine_log.txt", logFileName.c_str()))
|
||||
{
|
||||
__LOG_E__ << "Engine log copied to: " << logFileName << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
__LOG_E__ << "Failed to copy engine log to: " << logFileName << "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__LOG_E__ << "Engine log file 'g_engine_log.txt' not found for copying\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
static SQInteger SqRuntimeError(HSQUIRRELVM v)
|
||||
{
|
||||
SquirrelVM *vm = (SquirrelVM *)sq_getforeignptr(v);
|
||||
|
||||
// Get error string.
|
||||
const SQChar *error = NULL;
|
||||
if (SQ_FAILED(sq_getstring(v, 2, &error)))
|
||||
error = "Unspecified runtime error";
|
||||
|
||||
// Could be null if called from a coroutine.
|
||||
if (vm && (vm->GetState() == IVM::StateOk))
|
||||
{
|
||||
vm->SetState(IVM::StateExceptionThrown);
|
||||
|
||||
// Redirect to the signal handler.
|
||||
if (vm->GetEventHandler())
|
||||
{
|
||||
vm->GetEventHandler()->OnRuntimeException(error);
|
||||
return sq_suspendvm(v); // All debugging hope is lost beyond this point as the Squirrel VM will unwind all exception stack frame.
|
||||
}
|
||||
else
|
||||
{
|
||||
String msg = String::Format("Script runtime exception:\n\n%s", error);
|
||||
|
||||
AutoList <IVM::CallStackEntry *> callstack;
|
||||
vm->GetCallStack(callstack);
|
||||
|
||||
msg += "\n\nCallstack:\n\n";
|
||||
ListForeachPtr(IVM::CallStackEntry *, cs, callstack)
|
||||
msg += String::Format(" - %s() (line %d) in \"%s\"\n", cs->function.c_str(), cs->line, cs->source.c_str());
|
||||
|
||||
__LOG_E__ << "Squirrel Compiler Error: '" << msg << "'\n";
|
||||
|
||||
time_t now = time(NULL);
|
||||
struct tm *timeinfo = localtime(&now);
|
||||
char timestamp[64];
|
||||
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d_%H-%M-%S", timeinfo);
|
||||
|
||||
String logFileName = String::Format("g_engine_log_%s.txt", timestamp);
|
||||
|
||||
// Check if g_engine_log.txt exists and copy it
|
||||
if (Platform::Get().io->Exists("g_engine_log.txt"))
|
||||
{
|
||||
if (Platform::Get().io->FileCopy("g_engine_log.txt", logFileName.c_str()))
|
||||
{
|
||||
__LOG_E__ << "Engine log copied to: " << logFileName << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
__LOG_E__ << "Failed to copy engine log to: " << logFileName << "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__LOG_E__ << "Engine log file 'g_engine_log.txt' not found for copying\n";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return sq_suspendvm(v);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void SquirrelVM::SetDebugInterface(IDebug *i, bool debug)
|
||||
{
|
||||
sq_enabledebuginfo(vm, debug);
|
||||
/* if (vm)
|
||||
{
|
||||
sq_enabledebuginfo(vm, debug);
|
||||
if (debug)
|
||||
sq_setnativedebughook(vm, SqDebugHook);
|
||||
}
|
||||
IVM::SetDebugInterface(i, debug);*/
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void SquirrelVM::DumpCallStack(HSQUIRRELVM v, const char *desc, String *msg)
|
||||
{
|
||||
SQStackInfos si;
|
||||
// SQInteger level = 1; // Level 0 is the native closure we are in.
|
||||
|
||||
__LOG_V__ << "\n";
|
||||
String _msg(String::Format("Call stack (%s):\n", desc ? desc : "Requested"));
|
||||
__LOG_V__ << _msg.c_str();
|
||||
|
||||
for (SQInteger level = 1; SQ_SUCCEEDED(sq_stackinfos(v, level, &si)); ++level)
|
||||
{
|
||||
String _lg;
|
||||
|
||||
if (si.funcname)
|
||||
{
|
||||
if (si.line != -1)
|
||||
_lg = String::Format(" %d: %s() %s(%d)", level, si.funcname, si.source, si.line);
|
||||
else _lg = String::Format(" %d: %s() C/C++", level, si.funcname);
|
||||
}
|
||||
else
|
||||
_lg = String::Format(" %d: NOINFO", level);
|
||||
|
||||
__LOG_V__ << _lg << "\n";
|
||||
_msg += _lg;
|
||||
}
|
||||
|
||||
if (msg)
|
||||
*msg = _msg;
|
||||
__LOG_V__ << "\n";
|
||||
}
|
||||
bool SquirrelVM::Compile(const char *source, uint size, const Object *context, const char *sourcename)
|
||||
{
|
||||
if (!source)
|
||||
return false;
|
||||
|
||||
if (SQ_SUCCEEDED(sq_compilebuffer(vm, source, size, sourcename, true)))
|
||||
{
|
||||
sq_pushroottable(vm);
|
||||
sq_call(vm, 1, SQFalse, SQTrue);
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Object *SquirrelVM::GetObjectFromStack(int idx)
|
||||
{
|
||||
HSQOBJECT o;
|
||||
sq_getstackobj(vm, idx, &o);
|
||||
return new SquirrelObject(*this, o);
|
||||
}
|
||||
Object *SquirrelVM::GetObjectFromName(const char *name, const Object *context)
|
||||
{
|
||||
if (context)
|
||||
sq_pushobject(vm, ((const SquirrelObject *)context)->object);
|
||||
else sq_pushroottable(vm);
|
||||
|
||||
sq_pushstring(vm, name, -1);
|
||||
if (SQ_FAILED(sq_get(vm, -2)))
|
||||
{
|
||||
sq_pop(vm, 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Object *o = GetObjectFromStack(-1);
|
||||
sq_pop(vm, 2);
|
||||
return o;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool SquirrelVM::SetupFunctionCall(const char *func, const Object *cache, const Object *context)
|
||||
{
|
||||
if (!vm || (GetState() != StateOk))
|
||||
return false;
|
||||
|
||||
if (cache)
|
||||
sq_pushobject(vm, ((SquirrelObject *)cache)->object);
|
||||
else
|
||||
{
|
||||
if (context)
|
||||
sq_pushobject(vm, ((SquirrelObject *)context)->object);
|
||||
else sq_pushroottable(vm);
|
||||
|
||||
sq_pushstring(vm, func, -1);
|
||||
if (SQ_FAILED(sq_get(vm, -2)))
|
||||
{
|
||||
sq_pop(vm, 1); // Cleanup root table.
|
||||
return false;
|
||||
}
|
||||
sq_remove(vm, -2); // Remove root table.
|
||||
}
|
||||
|
||||
// Push function environment.
|
||||
if (context)
|
||||
sq_pushobject(vm, ((SquirrelObject *)context)->object);
|
||||
else sq_pushroottable(vm);
|
||||
|
||||
call_arg_count = 1;
|
||||
return true;
|
||||
}
|
||||
bool SquirrelVM::SetFunctionCallContext(const Script::Variant &v)
|
||||
{
|
||||
return PushArgument(v);
|
||||
}
|
||||
bool SquirrelVM::PushNullArgument()
|
||||
{
|
||||
call_arg_count++;
|
||||
return PushNull();
|
||||
}
|
||||
bool SquirrelVM::PushArgument(const Script::Variant &v)
|
||||
{
|
||||
call_arg_count++;
|
||||
return PushVariant(v);
|
||||
}
|
||||
bool SquirrelVM::DoFunctionCall(Script::Variant *v)
|
||||
{
|
||||
if (GetState() != StateOk)
|
||||
return false;
|
||||
if (SQ_FAILED(sq_call(vm, call_arg_count, SQTrue, SQTrue)))
|
||||
return false;
|
||||
|
||||
if (v)
|
||||
GetVariantFromStack(-1, *v);
|
||||
sq_pop(vm, 2);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool SquirrelVM::GetVariantFromStack(int idx, Script::Variant &v)
|
||||
{
|
||||
switch (sq_gettype(vm, idx))
|
||||
{
|
||||
case OT_STRING:
|
||||
{
|
||||
const SQChar *s;
|
||||
sq_getstring(vm, idx, &s);
|
||||
v.Set((const char *)s);
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_BOOL:
|
||||
{
|
||||
SQBool b;
|
||||
sq_getbool(vm, idx, &b);
|
||||
v.Set(asbool(b));
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_INTEGER:
|
||||
{
|
||||
SQInteger i;
|
||||
sq_getinteger(vm, idx, &i);
|
||||
v.Set((int)i);
|
||||
}
|
||||
break;
|
||||
|
||||
case OT_FLOAT:
|
||||
{
|
||||
SQFloat f;
|
||||
sq_getfloat(vm, idx, &f);
|
||||
v.Set((float)f);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
HSQOBJECT o;
|
||||
sq_getstackobj(vm, idx, &o);
|
||||
v.Set(new SquirrelObject(*this, o), true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool SquirrelVM::Get(const char *name, Script::Variant &prop, const Object *context)
|
||||
{
|
||||
if (context)
|
||||
sq_pushobject(vm, ((SquirrelObject *)context)->object);
|
||||
else sq_pushroottable(vm);
|
||||
sq_pushstring(vm, name, -1);
|
||||
if (SQ_FAILED(sq_get(vm, -2)))
|
||||
{
|
||||
sq_pop(vm, 1);
|
||||
return false;
|
||||
}
|
||||
bool r = GetVariantFromStack(-1, prop);
|
||||
sq_pop(vm, 2);
|
||||
return r;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool SquirrelVM::PushNull()
|
||||
{
|
||||
sq_pushnull(vm);
|
||||
return true;
|
||||
}
|
||||
bool SquirrelVM::PushVariant(const Script::Variant &v)
|
||||
{
|
||||
switch (v.type)
|
||||
{
|
||||
case Variant::Type_Variant:
|
||||
switch (v.variant.GetType())
|
||||
{
|
||||
case GS::Variant::VariantString:
|
||||
sq_pushstring(vm, v.variant.s_value.c_str(), -1);
|
||||
break;
|
||||
case GS::Variant::VariantInteger:
|
||||
sq_pushinteger(vm, v.variant.i_value);
|
||||
break;
|
||||
case GS::Variant::VariantBool:
|
||||
sq_pushbool(vm, v.variant.b_value);
|
||||
break;
|
||||
case GS::Variant::VariantFloat:
|
||||
sq_pushfloat(vm, v.variant.f_value);
|
||||
break;
|
||||
|
||||
default:
|
||||
__LOG_E__ << "Unsupported variant type: " << v.type << ".\n";
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case Variant::Type_ScriptObject:
|
||||
sq_pushobject(VM(), ((SquirrelObject *)v.object)->object);
|
||||
break;
|
||||
|
||||
case Variant::Type_UserObject:
|
||||
return CObject::Push(VM(), v.ptr, CObjectType(v.typetag));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool SquirrelVM::Set(const char *name, const Script::Variant &v, const Object *context)
|
||||
{
|
||||
if (context)
|
||||
sq_pushobject(vm, ((SquirrelObject *)context)->object);
|
||||
else sq_pushroottable(vm);
|
||||
sq_pushstring(vm, name, -1);
|
||||
if (!PushVariant(v))
|
||||
{
|
||||
sq_pop(vm, 2);
|
||||
return false;
|
||||
}
|
||||
SQObjectType type = sq_gettype(vm, -3);
|
||||
if ((type == OT_CLASS) || (type == OT_TABLE))
|
||||
sq_newslot(vm, -3, false);
|
||||
else sq_set(vm, -3);
|
||||
sq_pop(vm, 1);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Object *SquirrelVM::CreateArray()
|
||||
{
|
||||
sq_newarray(vm, 0);
|
||||
Object *o = GetObjectFromStack(-1);
|
||||
sq_pop(vm, 1);
|
||||
return o;
|
||||
}
|
||||
bool SquirrelVM::Append(const Script::Variant &prop, const Object *context)
|
||||
{
|
||||
if (context)
|
||||
sq_pushobject(vm, ((SquirrelObject *)context)->object);
|
||||
else sq_pushroottable(vm);
|
||||
if (!PushVariant(prop))
|
||||
{
|
||||
sq_pop(vm, 1);
|
||||
return false;
|
||||
}
|
||||
sq_arrayappend(vm, -2);
|
||||
sq_pop(vm, 1);
|
||||
return true;
|
||||
}
|
||||
Object *SquirrelVM::CreateTable()
|
||||
{
|
||||
sq_newtable(vm);
|
||||
Object *o = GetObjectFromStack(-1);
|
||||
sq_pop(vm, 1);
|
||||
return o;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool SquirrelVM::Open()
|
||||
{
|
||||
if (vm)
|
||||
return true;
|
||||
|
||||
vm = sq_open(1024);
|
||||
if (!vm)
|
||||
return false;
|
||||
|
||||
sq_setforeignptr(vm, (SQUserPointer)this);
|
||||
|
||||
sq_setcompilererrorhandler(vm, SqCompilerError);
|
||||
sq_setprintfunc(vm, SqPrintFunc, SqPrintFunc);
|
||||
sq_newclosure(vm, SqRuntimeError, 0);
|
||||
sq_seterrorhandler(vm);
|
||||
|
||||
sq_pushroottable(vm);
|
||||
sqstd_register_bloblib(vm);
|
||||
sqstd_register_iolib(vm);
|
||||
sqstd_register_systemlib(vm);
|
||||
sqstd_register_mathlib(vm);
|
||||
sqstd_register_stringlib(vm);
|
||||
sq_pop(vm, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
void SquirrelVM::Close()
|
||||
{
|
||||
//if (vm)
|
||||
// sq_close(vm);
|
||||
|
||||
vm = NULL;
|
||||
state = StateOk;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SquirrelObject::SquirrelObject(SquirrelVM &_vm, HSQOBJECT _object) : Object(_vm)
|
||||
{
|
||||
object = _object;
|
||||
sq_addref(((SquirrelVM &)vm).VM(), &object);
|
||||
}
|
||||
SquirrelObject::~SquirrelObject()
|
||||
{
|
||||
sq_release(((SquirrelVM &)vm).VM(), &object);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SquirrelVM::SquirrelVM()
|
||||
{
|
||||
vm = NULL;
|
||||
call_arg_count = 0;
|
||||
}
|
||||
SquirrelVM::~SquirrelVM()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
201
include/modules/tools/geometry_merge.cpp
Normal file
201
include/modules/tools/geometry_merge.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "tools/geometry_merge.h"
|
||||
#include "core/geometry.h"
|
||||
#include "math/matrix4.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::Core;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Geometry *GS::Core::MergeGeometry(Geometry *geo_a, Geometry *geo_b, const Matrix4 *mtx_a, const Matrix4 *mtx_b)
|
||||
{
|
||||
if (!geo_a || !geo_b)
|
||||
__ERR__(__LOG_E__ << "Cannot merge NULL geometry.\n", NULL)
|
||||
|
||||
if (!mtx_a)
|
||||
mtx_a = &Matrix4::IdentityMatrix();
|
||||
if (!mtx_b)
|
||||
mtx_b = &Matrix4::IdentityMatrix();
|
||||
|
||||
// Allocate a new geometry.
|
||||
Geometry *geo_o = new Geometry;
|
||||
if (!geo_o)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate merged geometry.\n", NULL)
|
||||
|
||||
geo_o->name = geo_a->name; // Nothing fancy here, the string length would blow up on large merge.
|
||||
|
||||
// Update data for all geometries.
|
||||
if (geo_a->pol_normal || geo_b->pol_normal)
|
||||
{
|
||||
geo_a->ComputePolygonNormal();
|
||||
geo_b->ComputePolygonNormal();
|
||||
}
|
||||
if (geo_a->vtx_normal || geo_b->vtx_normal)
|
||||
{
|
||||
geo_a->ComputeVertexNormal();
|
||||
geo_b->ComputeVertexNormal();
|
||||
}
|
||||
|
||||
// Append vertex.
|
||||
if (geo_o->vtx.Allocate(geo_a->vtx.GetCount() + geo_b->vtx.GetCount()))
|
||||
{
|
||||
Vector4 *pvtx = &geo_o->vtx[0];
|
||||
for (uint n = 0; n < geo_a->vtx.GetCount(); ++n)
|
||||
*pvtx++ = geo_a->vtx[n] * *mtx_a;
|
||||
for (uint n = 0; n < geo_b->vtx.GetCount(); ++n)
|
||||
*pvtx++ = geo_b->vtx[n] * *mtx_b;
|
||||
}
|
||||
|
||||
// Append polygon.
|
||||
if (geo_o->binding.Allocate(geo_a->binding.GetCount() + geo_b->binding.GetCount()))
|
||||
{
|
||||
uint *pbind = &geo_o->binding[0];
|
||||
for (uint n = 0; n < geo_a->binding.GetCount(); ++n)
|
||||
*pbind++ = geo_a->binding[n];
|
||||
for (uint n = 0; n < geo_b->binding.GetCount(); ++n)
|
||||
*pbind++ = geo_b->binding[n] + geo_a->vtx.GetCount();
|
||||
}
|
||||
|
||||
if (geo_o->pol.Allocate(geo_a->pol.GetCount() + geo_b->pol.GetCount()))
|
||||
{
|
||||
uint total_binding = 0;
|
||||
|
||||
Polygon *ppol = &geo_o->pol[0];
|
||||
for (uint n = 0; n < geo_a->pol.GetCount(); ++n)
|
||||
{
|
||||
ppol->vtx_count = geo_a->pol[n].vtx_count;
|
||||
ppol->material = geo_a->pol[n].material;
|
||||
ppol->binding = &geo_o->binding[total_binding];
|
||||
total_binding += ppol->vtx_count;
|
||||
ppol++;
|
||||
}
|
||||
for (uint n = 0; n < geo_b->pol.GetCount(); ++n)
|
||||
{
|
||||
ppol->vtx_count = geo_b->pol[n].vtx_count;
|
||||
ppol->material = (ushort)(geo_b->pol[n].material + geo_a->material_table.GetCount());
|
||||
ppol->binding = &geo_o->binding[total_binding];
|
||||
total_binding += ppol->vtx_count;
|
||||
ppol++;
|
||||
}
|
||||
}
|
||||
|
||||
// Append polygon normal.
|
||||
static Vector4 default_normal(0, 0, 1);
|
||||
|
||||
if (geo_a->pol_normal || geo_b->pol_normal)
|
||||
if (geo_o->pol_normal.Allocate(geo_o->pol.GetCount()))
|
||||
{
|
||||
Vector4 *ppnrm = &geo_o->pol_normal[0];
|
||||
for (uint n = 0; n < geo_a->pol.GetCount(); ++n)
|
||||
{
|
||||
if (geo_a->pol_normal)
|
||||
{
|
||||
mtx_a->ApplyRotation(ppnrm, &geo_a->pol_normal[n]);
|
||||
*ppnrm++ = ppnrm->Normalized();
|
||||
}
|
||||
else
|
||||
*ppnrm++ = default_normal;
|
||||
}
|
||||
for (uint n = 0; n < geo_b->pol.GetCount(); ++n)
|
||||
{
|
||||
if (geo_b->pol_normal)
|
||||
{
|
||||
mtx_b->ApplyRotation(ppnrm, &geo_b->pol_normal[n]);
|
||||
*ppnrm++ = ppnrm->Normalized();
|
||||
}
|
||||
else
|
||||
*ppnrm++ = default_normal;
|
||||
}
|
||||
}
|
||||
|
||||
// Append vertex normal.
|
||||
if (geo_a->vtx_normal || geo_b->vtx_normal)
|
||||
if (geo_o->vtx_normal.Allocate(geo_o->binding.GetCount()))
|
||||
{
|
||||
Vector4 *pvnrm = &geo_o->vtx_normal[0];
|
||||
for (uint n = 0; n < geo_a->binding.GetCount(); ++n)
|
||||
{
|
||||
if (geo_a->vtx_normal)
|
||||
{
|
||||
mtx_a->ApplyRotation(pvnrm, &geo_a->vtx_normal[n]);
|
||||
*pvnrm++ = pvnrm->Normalized();
|
||||
}
|
||||
else
|
||||
*pvnrm++ = Vector4(0, 0, 1);
|
||||
}
|
||||
for (uint n = 0; n < geo_b->binding.GetCount(); ++n)
|
||||
{
|
||||
if (geo_b->vtx_normal)
|
||||
{
|
||||
mtx_b->ApplyRotation(pvnrm, &geo_b->vtx_normal[n]);
|
||||
*pvnrm++ = pvnrm->Normalized();
|
||||
}
|
||||
else
|
||||
*pvnrm++ = Vector4(0, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Append RGB.
|
||||
if (geo_a->rgb || geo_b->rgb)
|
||||
if (geo_o->rgb.Allocate(geo_o->binding.GetCount()))
|
||||
{
|
||||
Color *prgb = &geo_o->rgb[0];
|
||||
for (uint n = 0; n < geo_a->binding.GetCount(); ++n)
|
||||
*prgb++ = geo_a->rgb ? geo_a->rgb[n] : Color::White;
|
||||
for (uint n = 0; n < geo_b->binding.GetCount(); ++n)
|
||||
*prgb++ = geo_b->rgb ? geo_b->rgb[n] : Color::White;
|
||||
}
|
||||
|
||||
// Append all UV channels.
|
||||
static Vector2 default_uv(0.5, 0.5);
|
||||
|
||||
for (uint n = 0; n < __UV_PER_GEOMETRY__; ++n)
|
||||
if (geo_a->uv[n] || geo_b->uv[n])
|
||||
if (geo_o->uv[n].Allocate(geo_o->binding.GetCount()))
|
||||
{
|
||||
Vector2 *puv = &geo_o->uv[n][0];
|
||||
|
||||
if (geo_a->uv[n])
|
||||
for (uint v = 0; v < geo_a->binding.GetCount(); ++v)
|
||||
*puv++ = geo_a->uv[n][v];
|
||||
else
|
||||
for (uint v = 0; v < geo_a->binding.GetCount(); ++v)
|
||||
*puv++ = default_uv;
|
||||
|
||||
if (geo_b->uv[n])
|
||||
for (uint v = 0; v < geo_b->binding.GetCount(); ++v)
|
||||
*puv++ = geo_b->uv[n][v];
|
||||
else
|
||||
for (uint v = 0; v < geo_b->binding.GetCount(); ++v)
|
||||
*puv++ = default_uv;
|
||||
}
|
||||
|
||||
// Append all materials.
|
||||
geo_o->material_table.Allocate(geo_a->material_table.GetCount() + geo_b->material_table.GetCount());
|
||||
Geometry::MaterialSlot *pslot = geo_o->material_table.c_ptr();
|
||||
|
||||
for (uint n = 0; n < geo_a->material_table.GetCount(); ++n)
|
||||
{
|
||||
pslot->name = geo_a->material_table[n].name;
|
||||
pslot->use_cache = geo_a->material_table[n].use_cache;
|
||||
++pslot;
|
||||
}
|
||||
for (uint n = 0; n < geo_b->material_table.GetCount(); ++n)
|
||||
{
|
||||
pslot->name = geo_b->material_table[n].name;
|
||||
pslot->use_cache = geo_b->material_table[n].use_cache;
|
||||
++pslot;
|
||||
}
|
||||
|
||||
// Merge materials.
|
||||
geo_o->MergeDuplicateMaterials();
|
||||
|
||||
return geo_o;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
235
include/modules/tools/resource_explorer.cpp
Normal file
235
include/modules/tools/resource_explorer.cpp
Normal file
@ -0,0 +1,235 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "tools/resource_explorer.h"
|
||||
#include "metafile/nml.h"
|
||||
#include "platform.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
|
||||
using namespace GS::Resource;
|
||||
using namespace GS::NML;
|
||||
using GS::String;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
DependencyRule scene3d_dependency_rules[] =
|
||||
{
|
||||
// Instances
|
||||
{ "Items/*Instance/Template", "Scene" },
|
||||
|
||||
// Terrains
|
||||
{ "Items/*MTerrain/Terrain/Blendmap", "Texture" },
|
||||
{ "Items/*MTerrain/Terrain/Blendmap", "Shader" },
|
||||
{ "Items/*MTerrain/Terrain/MaterialName", "Material" },
|
||||
{ "Items/*MTerrain/Terrain/Heightmap/Data", "Data" },
|
||||
{ "Items/*MTerrain/Terrain/Layers/*Layer/Diffuse", "Texture" },
|
||||
{ "Items/*MTerrain/Terrain/Layers/*Layer/Normal", "Texture" },
|
||||
{ "Items/*MTerrain/Terrain/Layers/*Layer/Specular", "Texture" },
|
||||
{ "Items/*MTerrain/Terrain/Layers/*Layer/Self", "Texture" },
|
||||
|
||||
// Lights
|
||||
{ "Items/*MLight/Light/ProjectionMap", "Texture" },
|
||||
|
||||
// Objects
|
||||
{ "Items/*MObject/Object/Geometry", "Geometry" },
|
||||
|
||||
// All items
|
||||
{ "Items/*/MItem/ScriptedObject/*ScriptUnit/Script", "Script" }, // legacy
|
||||
{ "Items/*/MItem/ScriptedObject/*ScriptUnit/ScriptPath", "Script" },
|
||||
{ "Items/*/MItem/PhysicItem/Shapes/*PhysicShape/Mesh", "Geometry" },
|
||||
|
||||
// Scene
|
||||
{ "ScriptedObject/*ScriptUnit/Script", "Script" }, // legacy
|
||||
{ "ScriptedObject/*ScriptUnit/ScriptPath", "Script" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
DependencyRule geometry_dependency_rules[] =
|
||||
{
|
||||
{ "Materials/*MaterialRef", "Material" },
|
||||
{ "Materials/*MaterialRefEx/Name", "Material" },
|
||||
|
||||
{ "LodProxy", "Geometry" },
|
||||
{ "ShadowProxy", "Geometry" },
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
DependencyRule material_dependency_rules[] =
|
||||
{
|
||||
{ "*TextureStage/Texture", "Texture" },
|
||||
{ "Shader", "Shader" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
DependencyRule shader_tree_dependency_rules[] =
|
||||
{
|
||||
{ "Map/*Entry/Param/Texture", "Texture" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
DependencyRule shader_dependency_rules[] =
|
||||
{
|
||||
{ "Input/*Uniform/Texture", "Texture" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
ExplorerRule resource_rules[] =
|
||||
{
|
||||
{ "Scene3d", "Scene", scene3d_dependency_rules },
|
||||
{ "Geometry", "Geometry", geometry_dependency_rules },
|
||||
{ "Material", "Material", material_dependency_rules },
|
||||
{ "Shader Tree", "ShaderMap", shader_tree_dependency_rules },
|
||||
{ "Shader", "Shader", shader_dependency_rules },
|
||||
{ 0, 0 }
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
const char *Explorer::DependencyTag::GetName() const
|
||||
{ return tag->GetString(); }
|
||||
void Explorer::DependencyTag::SetName(const char *n)
|
||||
{ tag->SetString(n); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool resource_filter(const Explorer::Resource *r, const char *name) { return r->name == name; }
|
||||
bool dependency_filter(const Explorer::Dependency *d, const char *name) { return !String::strccmp(d->GetName(), name); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
const Explorer::Dependency *Explorer::Resource::FindDependency(const char *n) const
|
||||
{
|
||||
return ListFindEx(dependencies, dependency_filter, n);
|
||||
}
|
||||
bool Explorer::Resource::HasMissingDependencies() const
|
||||
{
|
||||
ListForeachPtr(Dependency *, dep, dependencies)
|
||||
if (dep->missing)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Explorer::ExploreResourceRuleTags(const GS::StringList &tags, uint pos, Tag *tag, Resource *r, int depth)
|
||||
{
|
||||
if (pos == tags.GetCount()) // end of path
|
||||
{
|
||||
if (tag->GetString())
|
||||
{
|
||||
String name = tag->GetString();
|
||||
|
||||
// if (!r->FindDependency(name))
|
||||
{
|
||||
DependencyTag *dependency = new DependencyTag(tag);
|
||||
r->dependencies.Add(dependency);
|
||||
|
||||
if (name.StartsWith("@sys/")) // engine generated resource
|
||||
dependency->missing = false;
|
||||
|
||||
else if (name.StartsWith("@core/"))
|
||||
dependency->missing = !Platform::Get().io->Exists(name);
|
||||
|
||||
// Assert dependency is found.
|
||||
else if (!name.IsAbsolutePath())
|
||||
{
|
||||
// Check in project path.
|
||||
if (!project_path.IsEmpty())
|
||||
{
|
||||
String _name = String::Format("%s/%s", project_path.c_str(), name.c_str()).CleanFilePath();
|
||||
if ((dependency->missing = !Platform::Get().io->Exists(_name)) == false)
|
||||
name = _name;
|
||||
}
|
||||
|
||||
// Check in core path if still missing.
|
||||
if (dependency->missing)
|
||||
if (!core_path.IsEmpty())
|
||||
{
|
||||
String _name = String::Format("%s/%s", core_path.c_str(), name.c_str()).CleanFilePath();
|
||||
if ((dependency->missing = !Platform::Get().io->Exists(_name)) == false)
|
||||
name = _name;
|
||||
}
|
||||
}
|
||||
ExploreResource(name, project_path, core_path, depth - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const String &t = tags[pos];
|
||||
|
||||
if (t.StartsWith("*")) // iterate current tag
|
||||
{
|
||||
String match = t.Mid(1);
|
||||
NMLTagForeach(c, *tag)
|
||||
if (match.IsEmpty() || (c->name == match))
|
||||
ExploreResourceRuleTags(tags, pos + 1, c, r, depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Tag *c = tag->GetTag(t)) // no tag means rule not met
|
||||
ExploreResourceRuleTags(tags, pos + 1, c, r, depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
bool Explorer::ExploreResourceRule(ExplorerRule &rule, Resource *r, int depth)
|
||||
{
|
||||
Tag *tag = r->file->GetTag(rule.root);
|
||||
if (!tag)
|
||||
return false;
|
||||
|
||||
r->type = rule.type;
|
||||
|
||||
for (int n = 0; rule.rules[n].type; ++n)
|
||||
{
|
||||
// Split rule tags.
|
||||
StringList tags;
|
||||
String(rule.rules[n].path).Split("/", tags);
|
||||
|
||||
ExploreResourceRuleTags(tags, 0, tag, r, depth);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Explorer::Resource *Explorer::ExploreResource(const char *name, const char *_project_path, const char *_core_path, int depth)
|
||||
{
|
||||
if (depth <= 0)
|
||||
return NULL;
|
||||
|
||||
project_path = _project_path;
|
||||
core_path = _core_path;
|
||||
|
||||
// Metafile.
|
||||
if (!Parser::IsMetafile(name))
|
||||
return NULL;
|
||||
|
||||
// Check if that resource has already been loaded.
|
||||
if (Resource *_r = ListFindEx(resources, resource_filter, name))
|
||||
return _r;
|
||||
|
||||
// Load file.
|
||||
AutoPtr <Resource> r(new Resource(name, "Null"));
|
||||
r->file = Parser::Load(name);
|
||||
if (r->file.IsNull())
|
||||
return NULL;
|
||||
|
||||
// Explore resource.
|
||||
for (int n = 0; resource_rules[n].type; ++n)
|
||||
if (ExploreResourceRule(resource_rules[n], r, depth))
|
||||
{
|
||||
resources.Add(r);
|
||||
return r.Detach();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
const Explorer::Resource *Explorer::FindResource(const char *name) const
|
||||
{
|
||||
return ListFindEx(resources, resource_filter, name);
|
||||
}
|
||||
void Explorer::Clear()
|
||||
{
|
||||
resources.Clear();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
186
include/modules/tools/scene_merge_object_list.cpp
Normal file
186
include/modules/tools/scene_merge_object_list.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "tools/scene_merge_object_list.h"
|
||||
#include "tools/geometry_merge.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "physic/physic_world.h"
|
||||
#include "core/graphic_resource_factory.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::S3D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct ItemTransform
|
||||
{
|
||||
sMItem i;
|
||||
Matrix4 m;
|
||||
|
||||
ItemTransform(MItem *_i, const Matrix4 &_m) : i(_i), m(_m) {}
|
||||
};
|
||||
struct GeometryTransform
|
||||
{
|
||||
sMItem i;
|
||||
Matrix4 m;
|
||||
sGeometry g;
|
||||
|
||||
GeometryTransform(MItem *_i, Geometry *_g, const Matrix4 &_m) : i(_i), m(_m), g(_g) {}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void MergePhysicShape(MItem *to, MItem *from)
|
||||
{
|
||||
if (!from->physic_item)
|
||||
return;
|
||||
|
||||
ListForeachPtr(PhysicShape *, shape, from->physic_item_desc.shape_list)
|
||||
if (PhysicShape *new_shape = new PhysicShape)
|
||||
{
|
||||
new_shape->SetMatrix(from->GetBaseItem()->GetMatrix() * shape->GetMatrix());
|
||||
new_shape->mass = shape->mass;
|
||||
|
||||
switch (shape->GetType())
|
||||
{
|
||||
case PhysicShape::TypeNone:
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeHeightmap:
|
||||
__LOG_W__ << "Merge heightmap physic shape STUB.\n";
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeBox:
|
||||
case PhysicShape::TypeCapsule:
|
||||
case PhysicShape::TypeCylinder:
|
||||
case PhysicShape::TypeCone:
|
||||
case PhysicShape::TypeSphere:
|
||||
new_shape->Set(shape->GetType(), shape->dimensions);
|
||||
break;
|
||||
|
||||
case PhysicShape::TypeConvex:
|
||||
case PhysicShape::TypeMesh:
|
||||
new_shape->Set(shape->GetType(), shape->path);
|
||||
break;
|
||||
}
|
||||
|
||||
to->physic_item_desc.shape_list.Add(new_shape);
|
||||
}
|
||||
|
||||
to->physic_item_desc.physic_mode = from->physic_item_desc.physic_mode;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool SceneMergeObjectList::Merge(Scene *scene, const SharedList <MItem *> &item_list, Core::ResourceFactory &gf, sMItem &out_item, sGeometry &out_geo)
|
||||
{
|
||||
// Unlink all children, store matrix beforehand.
|
||||
AutoList <ItemTransform *> child_list;
|
||||
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
ListForeachPtr(Item *, child, item->GetBaseItem()->GetChildren())
|
||||
{
|
||||
MItem *cchild = Scene::LocateManagedItem(child);
|
||||
|
||||
// Do not store item if it is going to be merged.
|
||||
if (!item_list.Find(cchild))
|
||||
child_list.Add(new ItemTransform(cchild, cchild->GetBaseItem()->GetMatrix()));
|
||||
}
|
||||
|
||||
Vector4 average_vec(0.0,0.0,0.0);
|
||||
int counter_average = 0;
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (item->GetItemType() == Type_Object)
|
||||
{
|
||||
++counter_average;
|
||||
average_vec += item->GetBaseItem()->GetPosition();
|
||||
}
|
||||
|
||||
average_vec /= counter_average;
|
||||
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (item->GetItemType() == Type_Object)
|
||||
item->GetBaseItem()->SetPosition(item->GetBaseItem()->GetPosition() - average_vec);
|
||||
|
||||
// Build merge list.
|
||||
AutoList <GeometryTransform *> geo_list;
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (item->GetItemType() == Type_Object)
|
||||
geo_list.Add(new GeometryTransform(item, gf.LoadGeometry(((MObject *)item)->geometry), item->GetBaseItem()->GetMatrix()));
|
||||
|
||||
if (geo_list.GetCount() < 2)
|
||||
return true; // nothing to be done
|
||||
|
||||
// Count total steps.
|
||||
int total_step_count = 0;
|
||||
for (int count = item_list.GetCount(); count > 1; count /= 2)
|
||||
total_step_count += count;
|
||||
|
||||
// Merge list.
|
||||
AutoList <GeometryTransform *> tgt_list, *in_list = &geo_list, *out_list = &tgt_list;
|
||||
|
||||
int step_count = 0;
|
||||
for (bool running = true; (in_list->GetCount() > 1) && running; )
|
||||
{
|
||||
for (uint n = 0; (n < in_list->GetCount()) && running; n += 2)
|
||||
{
|
||||
if (n == (in_list->GetCount() - 1))
|
||||
{
|
||||
GeometryTransform *t = (*in_list)[n];
|
||||
out_list->Add(new GeometryTransform(t->i, t->g, t->m));
|
||||
continue; // nothing to merge
|
||||
}
|
||||
|
||||
// Merge geometries.
|
||||
GeometryTransform *left = (*in_list)[n], *right = (*in_list)[n + 1];
|
||||
sGeometry merged_geometry(MergeGeometry(left->g, right->g, &left->m, &right->m));
|
||||
if (merged_geometry.IsNull())
|
||||
continue;
|
||||
|
||||
// Merge physic shapes.
|
||||
MObject *merged_object = new MObject;
|
||||
scene->SetupItemComponents(merged_object);
|
||||
MergePhysicShape(merged_object, left->i);
|
||||
MergePhysicShape(merged_object, right->i);
|
||||
|
||||
out_list->Add(new GeometryTransform(merged_object, merged_geometry, Matrix4::IdentityMatrix()));
|
||||
|
||||
running = OnProgress(++step_count, total_step_count);
|
||||
}
|
||||
in_list->Clear();
|
||||
|
||||
AutoList <GeometryTransform *> *tmp_list = in_list; in_list = out_list; out_list = tmp_list;
|
||||
}
|
||||
if (in_list->GetCount() != 1)
|
||||
return false;
|
||||
|
||||
// Remove merged items from scene.
|
||||
ListForeachPtr(MItem *, item, item_list)
|
||||
if (item->GetItemType() == Type_Object)
|
||||
scene->RemoveItem(item);
|
||||
|
||||
// Store output...
|
||||
out_item = (*in_list)[0]->i;
|
||||
out_geo = (*in_list)[0]->g;
|
||||
|
||||
out_item->GetBaseItem()->SetPosition(average_vec);
|
||||
|
||||
out_item->name = "Merged Object";
|
||||
scene->AddItem(out_item, false);
|
||||
|
||||
// ...restore parenting.
|
||||
ListForeachPtr(ItemTransform *, t, child_list)
|
||||
{
|
||||
t->i->GetBaseItem()->SetParent(out_item->GetBaseItem());
|
||||
t->i->GetBaseItem()->SnapshotTransformation(t->m);
|
||||
}
|
||||
child_list.Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
608
include/modules/viewer_base/viewer_base.cpp
Normal file
608
include/modules/viewer_base/viewer_base.cpp
Normal file
@ -0,0 +1,608 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "viewer_base/viewer_base.h"
|
||||
#include "viewer_base/viewer_base_debugger.h"
|
||||
#include "physic_bullet/bullet_world.h"
|
||||
#include "io_archive/io_archive.h"
|
||||
#include "raytracer/raytracer_core.h"
|
||||
#include "font_freetype/ft2_font_factory.h"
|
||||
#include "script_squirrel/engine_vm_debugger.h"
|
||||
#include "script_squirrel/engine_vm.h"
|
||||
#include "script/script_variant.h"
|
||||
#include "ui/ui.h"
|
||||
#include "gpu/gpu_triangle_batch.h"
|
||||
#include "gpu/gpu_renderer.h"
|
||||
#include "core/embedded_resource_extractor.h"
|
||||
#include "core/renderer_toolbox.h"
|
||||
#include "metafile/nml_object.h"
|
||||
#include "picture/pict_io.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "filesystem/io_cfile.h"
|
||||
#include "input/input_system.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::OpenViewer()
|
||||
{
|
||||
// Check core file system.
|
||||
if (!Platform::Get().io->Exists("@core/noise.tga"))
|
||||
__ERR__(__LOG_E__ << "@core is not properly mounted.\n", false)
|
||||
|
||||
// Embedded resources will be extracted to a ram disk.
|
||||
IEmbeddedResourceHandler::Set(new EmbeddedResourceExtractor(true));
|
||||
|
||||
// Create outputs.
|
||||
factories = new ResourceFactories;
|
||||
if (!CreateRenderer() || !CreateMixer())
|
||||
return false;
|
||||
|
||||
// Load renderer configuration.
|
||||
NML::Parser::Load(config_path, renderer->registry);
|
||||
|
||||
// Open output subsystems.
|
||||
if (!OpenVideo() || !OpenAudio())
|
||||
return false;
|
||||
|
||||
profiler_font[0] = new Render::RasterFont;
|
||||
profiler_font[0]->Load(*factories->render, "@core/fonts/profiler_base.nml", "@core/fonts/profiler_base");
|
||||
profiler_font[1] = new Render::RasterFont;
|
||||
profiler_font[1]->Load(*factories->render, "@core/fonts/profiler_bold.nml", "@core/fonts/profiler_bold");
|
||||
|
||||
fps_font = new Render::RasterFont;
|
||||
fps_font->Load(*factories->render, "@core/fonts/fps.nml", "@core/fonts/fps");
|
||||
|
||||
gpu_batch = new GPU::TriangleBatch((GPU::Renderer &)*renderer);
|
||||
|
||||
// Initialize input interface.
|
||||
Platform::Get().input_system->SetHandle(renderer->GetCurrentSystemWindowHandle());
|
||||
|
||||
state = SessionSetup;
|
||||
return true;
|
||||
}
|
||||
void ViewerBase::CloseViewer()
|
||||
{
|
||||
CloseSession();
|
||||
|
||||
for (uint n = 0; n < 2; ++n)
|
||||
_safe_delete(profiler_font[n]);
|
||||
_safe_delete(fps_font);
|
||||
|
||||
factories = NULL;
|
||||
|
||||
if (renderer.IsValid())
|
||||
{
|
||||
renderer->Close();
|
||||
renderer = NULL;
|
||||
}
|
||||
if (mixer.IsValid())
|
||||
{
|
||||
mixer->Close();
|
||||
mixer = NULL;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::SetupSessionSource() // session
|
||||
{
|
||||
switch (session_source)
|
||||
{
|
||||
case SessionSourceFilesystem:
|
||||
Platform::Get().io->Mount(new IO::CFile(session_source_path));
|
||||
break;
|
||||
case SessionSourceArchive:
|
||||
Platform::Get().io->Mount(new IO::Archive(session_source_path));
|
||||
break;
|
||||
case SessionSourceArchiveBootstrap:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::OpenScriptVM() // session
|
||||
{
|
||||
// Compile core library.
|
||||
if (!script_vm->CompileFile("@core/script/nad.nut"))
|
||||
return false;
|
||||
|
||||
// Set defines.
|
||||
ListForeachPtr(Variant *, prop, define_list)
|
||||
script_vm->Set(prop->id, *prop);
|
||||
|
||||
// Load optional includes.
|
||||
for (uint n = 0; n < include_list.GetCount(); ++n)
|
||||
if (!script_vm->CompileFile(include_list.ObjectAt(n)))
|
||||
return false;
|
||||
|
||||
// Compile bootstrap.
|
||||
if (!bootstrap_script.IsEmpty() && !script_vm->Compile(bootstrap_script, bootstrap_script.Len(), NULL, "Bootstrap"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
void ViewerBase::SetVMGlobals()
|
||||
{
|
||||
script_vm->Set("g_project", Script::Variant(project, Script::typetag_Project));
|
||||
|
||||
script_vm->Set("g_factory", Script::Variant(factories, Script::typetag_ResourceFactories));
|
||||
script_vm->Set("g_render", Script::Variant(renderer, Script::typetag_Renderer));
|
||||
script_vm->Set("g_mixer", Script::Variant(mixer, Script::typetag_Mixer));
|
||||
|
||||
script_vm->Set("g_dt_frame", 1.f / 60.f);
|
||||
script_vm->Set("g_raw_dt_frame", 1.f / 60.f);
|
||||
script_vm->Set("g_clock", 0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::LoadSessionData()
|
||||
{
|
||||
if (remote)
|
||||
session_type = remote_scene.isEmpty() ? SessionProject : SessionScene;
|
||||
|
||||
__LOG__ << "Session type: " << session_type << "\n";
|
||||
|
||||
using namespace NML;
|
||||
|
||||
if (session_type == SessionProject)
|
||||
{
|
||||
if (!remote)
|
||||
{
|
||||
if (!LoadFromFile(*project, input_path))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (!LoadFromFile(*project, remote_project))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!project->Open(session_type == SessionProject))
|
||||
return false;
|
||||
|
||||
switch (session_type)
|
||||
{
|
||||
case SessionScene:
|
||||
{
|
||||
// Determine the scene type.
|
||||
if (!remote)
|
||||
if (!Parser::Load(input_path, remote_scene)) // load local scene over the remote_scene meta file
|
||||
return false;
|
||||
|
||||
Tag *t_scene2d = remote_scene.GetTag("Scene2D"),
|
||||
*t_scene3d = remote_scene.GetTag("Scene");
|
||||
|
||||
//
|
||||
if (t_scene3d)
|
||||
{
|
||||
scene_3d = new S3D::Scene(script_vm);
|
||||
scene_3d->SetClock(project->clock);
|
||||
|
||||
if (!scene_3d->Create(project->iproject_factory->NewPhysicWorld()))
|
||||
return false;
|
||||
if (!scene_3d->FromMetaTag(*t_scene3d, tool_mode ? ToolPreview : NoTool))
|
||||
return false;
|
||||
|
||||
scene_3d->name = input_path;
|
||||
scene_3d->SetAsScriptGlobalScene();
|
||||
scene_3d->InstanceSetup();
|
||||
scene_3d->RenderSetup(factories);
|
||||
scene_3d->Setup(tool_mode ? ToolPreview : NoTool);
|
||||
scene_3d->Reset();
|
||||
}
|
||||
else if (t_scene2d)
|
||||
{
|
||||
scene_2d = new S2D::Scene(script_vm);
|
||||
scene_2d->SetClock(project->clock);
|
||||
|
||||
if (!scene_2d->FromMetaTag(*t_scene2d, tool_mode ? ToolPreview : NoTool))
|
||||
return false;
|
||||
|
||||
scene_2d->name = input_path;
|
||||
scene_2d->SetAsScriptGlobalScene();
|
||||
scene_2d->RenderSetup(factories);
|
||||
scene_2d->Setup();
|
||||
scene_2d->Reset();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SessionProject:
|
||||
project->Setup();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::OpenSession()
|
||||
{
|
||||
if (!OpenScriptVM())
|
||||
return false;
|
||||
|
||||
missing_resource = false;
|
||||
|
||||
// Create project.
|
||||
struct ProjectFactory : public IProjectFactory
|
||||
{ S3D::PhysicWorld *NewPhysicWorld() const { return new S3D::BulletWorld; } };
|
||||
|
||||
project = new Project(factories, new Freetype2FontFactory, script_vm);
|
||||
project->iproject_factory = new ProjectFactory;
|
||||
|
||||
SetVMGlobals();
|
||||
|
||||
// Setup data source.
|
||||
if (!SetupSessionSource())
|
||||
return false;
|
||||
|
||||
// Load viewer data.
|
||||
if (!LoadSessionData())
|
||||
return false;
|
||||
|
||||
time_start = Platform::Get().GetClock();
|
||||
return true;
|
||||
}
|
||||
void ViewerBase::CloseSession()
|
||||
{
|
||||
paused = false;
|
||||
|
||||
scene_2d = NULL;
|
||||
scene_3d = NULL;
|
||||
project = NULL;
|
||||
|
||||
// [EJ] explicitly close the VM now as is may hold references to render resources
|
||||
if (script_vm.IsValid())
|
||||
script_vm->Close();
|
||||
|
||||
// script_vm = NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ViewerBase::ExecuteSession()
|
||||
{
|
||||
if (scene_3d)
|
||||
scene_3d->profiler.ResetProfiles();
|
||||
|
||||
project->ResetStatistics();
|
||||
renderer->ResetStatistics();
|
||||
|
||||
// Start frame.
|
||||
if (!paused)
|
||||
{
|
||||
project->clock->Update();
|
||||
project->UpdateScriptClock();
|
||||
}
|
||||
|
||||
float x = 32, y = 32;
|
||||
bool end_session = false;
|
||||
|
||||
switch (session_type)
|
||||
{
|
||||
case SessionScene:
|
||||
if (scene_2d.IsValid())
|
||||
{
|
||||
renderer->Clear(0, 0, 0);
|
||||
|
||||
if (!paused)
|
||||
scene_2d->Update();
|
||||
|
||||
// nGPUTriangleBatch batch(*renderer);
|
||||
scene_2d->Render(*renderer/*, &batch*/);
|
||||
}
|
||||
if (scene_3d.IsValid())
|
||||
{
|
||||
if (!paused)
|
||||
scene_3d->Update();
|
||||
scene_3d->Render(*renderer);
|
||||
scene_3d->RenderUI(*renderer, gpu_batch);
|
||||
|
||||
// Viewer-specific
|
||||
{
|
||||
if (enable_profiler)
|
||||
scene_3d->DrawProfilerText(*renderer, profiler_font, x, y);
|
||||
|
||||
if (scene_3d->flags.IsSet(S3D::Scene::FlagEnd))
|
||||
end_session = true;
|
||||
|
||||
if (!raytrace_path.IsEmpty())
|
||||
{
|
||||
int w = raytrace_width == -1 ? width : raytrace_width,
|
||||
h = raytrace_height == -1 ? height : raytrace_height;
|
||||
|
||||
__LOG_H__ << "Raytracing frame " << frame_count << " (" << w << "x" << h << ")...\n";
|
||||
Raytrace::Raytracer ray(factories->graphic);
|
||||
|
||||
if (ray.SetScene(scene_3d))
|
||||
{
|
||||
Picture out;
|
||||
ray.GetConfiguration().aa_sample = raytrace_aa;
|
||||
if (ray.Render(out, w, h))
|
||||
PictureIO::Get().TgaSave(out, String::Format("%s/out_%05d.tga", raytrace_path.c_str(), frame_count));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SessionProject:
|
||||
if (!paused)
|
||||
project->Update(SceneUpdateAll);
|
||||
|
||||
project->Render(*renderer);
|
||||
|
||||
// Viewer-specific
|
||||
{
|
||||
if (enable_profiler)
|
||||
project->DrawProfilerText(*renderer, profiler_font, x, y);
|
||||
|
||||
if (project->flags.IsSet(Project::ProjectFlagEnd))
|
||||
end_session = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// End frame.
|
||||
fRect viewport = renderer->GetViewport();
|
||||
|
||||
if (enable_profiler)
|
||||
{
|
||||
float x = viewport.GetWidth() - 400.f, y = 32.f;
|
||||
renderer->DrawProfilerText(profiler_font, x, y);
|
||||
}
|
||||
else if (memory_profiler)
|
||||
{
|
||||
float x = 0, y = 0;
|
||||
DrawAllocProfilerText(*renderer, profiler_font, x, y);
|
||||
}
|
||||
|
||||
if (enable_profiler || display_fps)
|
||||
{
|
||||
Color shadow(0, 0, 0, 0.5);
|
||||
Render::Renderer::WriterConfig config(false);
|
||||
|
||||
float x = 32, y = viewport.GetHeight() - 102;
|
||||
renderer->Write(*fps_font, String::Format("%02.01f\n", fps.GetFps()), x, y, config, 1, &shadow);
|
||||
y = viewport.GetHeight() - 112;
|
||||
renderer->Write(*fps_font, String::Format("%02.01f\n", fps.GetFps()), x, y, config);
|
||||
}
|
||||
|
||||
renderer->ShowFrame();
|
||||
frame_count++;
|
||||
|
||||
// Pause support.
|
||||
/* if (Input::Device *keyboard = Platform::Get().input_system->GetDevice("keyboard"))
|
||||
if (keyboard->WasPressed(Input::Device::Key_P))
|
||||
{
|
||||
paused = !paused;
|
||||
if (!paused)
|
||||
project->clock->EatDeltaClock();
|
||||
}
|
||||
*/
|
||||
// Check session runtime error.
|
||||
if (CheckRuntimeError())
|
||||
end_session = true;
|
||||
if (time_live && ((Platform::Get().GetClock() - time_start) > (time_live * Platform::Get().GetClockFrequency())))
|
||||
end_session = true;
|
||||
|
||||
if (end_session)
|
||||
state = SessionClose;
|
||||
}
|
||||
bool ViewerBase::CheckRuntimeError()
|
||||
{
|
||||
// Check VM state.
|
||||
switch (script_vm->GetState())
|
||||
{
|
||||
case Script::IVM::StateDead:
|
||||
case Script::IVM::StateExceptionThrown:
|
||||
return true;
|
||||
|
||||
case Script::IVM::StateOk:
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for a missing resource error.
|
||||
if (missing_resource && !ignore_missing_resource)
|
||||
__ERR__(__LOG_E__ << "Closing session due to missing resources.\n", true)
|
||||
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Script::NetworkDebugger *ViewerBase::CreateVMDebugInterface()
|
||||
{
|
||||
return new Script::ViewerBaseDebugger(*this, new Script::EngineDebugger((Script::EngineVM &)*script_vm), NULL, remote_port);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
ViewerBase::State ViewerBase::Execute()
|
||||
{
|
||||
fps.MarkLoop();
|
||||
|
||||
Platform::Get().input_system->Update();
|
||||
bool platform_update = PlatformUpdate();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
//----------------------------------------------------------------------
|
||||
case ViewerSetup:
|
||||
script_vm = new Script::EngineVM;
|
||||
script_vm->Open();
|
||||
|
||||
if (active_debug)
|
||||
script_vm->SetDebugInterface(script_debugger, true);
|
||||
|
||||
if (remote)
|
||||
{
|
||||
script_debugger = CreateVMDebugInterface();
|
||||
script_vm->SetDebugInterface(script_debugger, true);
|
||||
|
||||
// @FIXME make sure the network thread is running ok.
|
||||
|
||||
__LOG_H__ << "Waiting for controller connection...\n";
|
||||
state = WaitRemoteController;
|
||||
}
|
||||
else
|
||||
state = SessionSetup; // local setup done
|
||||
break;
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
case WaitRemoteController:
|
||||
if (script_debugger && script_debugger->IsConnected())
|
||||
{
|
||||
__LOG_H__ << "Controller connected.\n";
|
||||
state = WaitRemoteSetup;
|
||||
}
|
||||
if (!platform_update)
|
||||
state = ViewerClose;
|
||||
break;
|
||||
|
||||
case WaitRemoteSetup:
|
||||
if (script_debugger && !script_debugger->IsConnected())
|
||||
{
|
||||
__LOG_H__ << "Controller lost, waiting for controller connection...\n";
|
||||
state = WaitRemoteController;
|
||||
}
|
||||
break; // state will be altered by the monitor
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
case SessionSetup:
|
||||
if (OpenViewer() && OpenSession())
|
||||
{
|
||||
__LOG_H__ << "Session running.\n";
|
||||
state = SessionRunning;
|
||||
}
|
||||
else
|
||||
state = remote ? WaitRemoteSetup : SessionClose;
|
||||
break;
|
||||
|
||||
case SessionRunning:
|
||||
ExecuteSession();
|
||||
|
||||
if (state == SessionRunning)
|
||||
{
|
||||
if (script_debugger && !script_debugger->IsConnected())
|
||||
state = SessionClose;
|
||||
|
||||
if (!platform_update)
|
||||
state = SessionClose;
|
||||
}
|
||||
|
||||
if (state != SessionRunning)
|
||||
__LOG_H__ << "Closing session.\n";
|
||||
break;
|
||||
|
||||
case SessionClose:
|
||||
CloseSession();
|
||||
CloseViewer();
|
||||
|
||||
if (remote)
|
||||
{
|
||||
script_debugger->Stop();
|
||||
|
||||
if (remote_fs.IsValid())
|
||||
{
|
||||
Platform::Get().io->Unmount(remote_fs);
|
||||
remote_fs = NULL;
|
||||
}
|
||||
|
||||
state = ViewerSetup;
|
||||
}
|
||||
else
|
||||
state = ViewerClose;
|
||||
break;
|
||||
|
||||
case ViewerClose:
|
||||
break;
|
||||
}
|
||||
|
||||
if (script_debugger)
|
||||
while (script_debugger->async.Execute());
|
||||
|
||||
Platform::Get().Sleep(1);
|
||||
return state;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ViewerBase::Suspend() // app sent to background (iOS/Android)
|
||||
{
|
||||
if (script_vm && script_vm->SetupFunctionCall("OnSuspend"))
|
||||
script_vm->DoFunctionCall();
|
||||
if (mixer)
|
||||
mixer->SuspendWorkerThread();
|
||||
}
|
||||
void ViewerBase::Resume() // app sent back to foreground (iOS/Android)
|
||||
{
|
||||
if (script_vm && script_vm->SetupFunctionCall("OnResume"))
|
||||
script_vm->DoFunctionCall();
|
||||
if (mixer)
|
||||
mixer->ResumeWorkerThread();
|
||||
|
||||
if (project.IsValid())
|
||||
project->clock->EatDeltaClock();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
ViewerBase::ViewerBase()
|
||||
{
|
||||
state = ViewerSetup;
|
||||
|
||||
paused = false;
|
||||
missing_resource = false;
|
||||
|
||||
time_start = 0;
|
||||
time_live = 0;
|
||||
frame_count = 0;
|
||||
|
||||
raytrace_width = -1;
|
||||
raytrace_height = -1;
|
||||
|
||||
session_source = SessionSourceFilesystem;
|
||||
session_type = SessionScene;
|
||||
session_source_path = "./";
|
||||
input_path = "scene.nms";
|
||||
|
||||
active_debug = false;
|
||||
|
||||
remote = false;
|
||||
remote_port = 999;
|
||||
|
||||
tool_mode = false;
|
||||
|
||||
script_debugger = NULL;
|
||||
|
||||
safe_mode = false;
|
||||
ignore_esc = false;
|
||||
ignore_missing_resource = false;
|
||||
fullscreen = false;
|
||||
|
||||
enable_profiler = false;
|
||||
memory_profiler = false;
|
||||
display_fps = false;
|
||||
|
||||
enable_pause = false;
|
||||
|
||||
for (int n = 0; n < 2; ++n)
|
||||
profiler_font[n] = NULL;
|
||||
fps_font = NULL;
|
||||
|
||||
width = 800;
|
||||
height = 600;
|
||||
aspect_ratio = 1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
431
include/modules/viewer_base/viewer_base_command_line.cpp
Normal file
431
include/modules/viewer_base/viewer_base_command_line.cpp
Normal file
@ -0,0 +1,431 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "viewer_base/viewer_base.h"
|
||||
#include <iostream>
|
||||
#include "io_archive/io_archive.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "core/engine.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "filesystem/io_cfile.h"
|
||||
#include "platform.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
// [EJ] 4/4: Do not use Log to output the command line as it will be eaten by a release build.
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ViewerBase::PrintHeader()
|
||||
{
|
||||
std::cout << "GameStart stand-alone.\n";
|
||||
std::cout << "http://www.gamestart3d.com\n";
|
||||
std::cout << "Version: " << Core::Version << "\n";
|
||||
std::cout << "Emmanuel Julien 2001-2013.\n\n";
|
||||
}
|
||||
String ViewerBase::GetBaseCommandLineParm() const
|
||||
{
|
||||
String parm;
|
||||
|
||||
parm << "Basic usage:\n\n";
|
||||
parm << "-P : Execute a project (default: execute scene).\n";
|
||||
parm << "-C <config path> : Configuration file path.\n";
|
||||
parm << "\n";
|
||||
|
||||
parm << "Data source (default: -f ./):\n\n";
|
||||
parm << "-f <base path> : Input data from the file system.\n";
|
||||
parm << "-A <archive path> : Input data from an archive.\n";
|
||||
parm << "-version <name> : Run a specific project version.\n";
|
||||
parm << "\n";
|
||||
|
||||
parm << "Resource path:\n\n";
|
||||
parm << "-CC <path> : Mount a file system directory as core.\n";
|
||||
parm << "-MD <path> <mount> : Mount a file system directory.\n";
|
||||
parm << "-S <path> : Add search path.\n";
|
||||
parm << "\n";
|
||||
|
||||
parm << "Data output (default: -r gl2 -m al):\n\n";
|
||||
parm << "-r <ID> : Output renderer ('list' for details).\n";
|
||||
parm << "-m <ID> : Output audio mixer ('nengine dummy -m list' for valid IDs).\n";
|
||||
parm << "-w <Width> : Display width in pixels.\n";
|
||||
parm << "-h <Height> : Display height in pixels.\n";
|
||||
parm << "\n";
|
||||
|
||||
parm << "Script interface:\n\n";
|
||||
parm << "-I <include> : Include a script.\n";
|
||||
parm << "-Ds <var> <string> : Define and initialize a variable.\n";
|
||||
parm << "-Di <var> <int> : Define and initialize a variable.\n";
|
||||
parm << "-Df <var> <float> : Define and initialize a variable.\n";
|
||||
parm << "\n";
|
||||
|
||||
parm << "Raytracer interface (scene view only):\n\n";
|
||||
parm << "-R <path> : Raytrace each frame to a directory.\n";
|
||||
parm << "-Rw <int> : Specify the raytracer frame width.\n";
|
||||
parm << "-Rh <int> : Specify the raytracer frame height.\n";
|
||||
parm << "-Raa <int> : Specify the raytracer AA grid size (default: 4).\n";
|
||||
parm << "\n";
|
||||
|
||||
parm << "Program flags:\n\n";
|
||||
parm << "-remote : Start the viewer in remote mode (must be first argument).\n";
|
||||
parm << "-remote_port <int> : Set the remote mode listening port.\n";
|
||||
parm << "\n";
|
||||
parm << "-ignore_esc : Do not exit when escape is pressed.\n";
|
||||
parm << "-ignore_missing : Do not exit on missing resource.\n";
|
||||
parm << "-ignore_bootstrap : Ignore the bootstrap file.\n";
|
||||
parm << "\n";
|
||||
parm << "-tool_mode : Execute as if ran in the editor.\n";
|
||||
parm << "-safe_mode : Enable renderer/mixer safe-mode.\n";
|
||||
parm << "\n";
|
||||
parm << "-enable_pause : Enable 'p' key to pause engine.\n";
|
||||
parm << "\n";
|
||||
parm << "-fallback_disk_fs : Enable disk file system fallback.\n";
|
||||
parm << "\n";
|
||||
parm << "-enable_profiler : Enable on-screen performance profiler.\n";
|
||||
parm << "-memory_profiler : Enable on-screen memory profiler.\n";
|
||||
parm << "\n";
|
||||
parm << "-log_level <mask> : Set the engine log level mask (eg. -log_level !S*).\n";
|
||||
parm << " n: None\n";
|
||||
parm << " s: Standard\n";
|
||||
parm << " H: Header\n";
|
||||
parm << " *: Warning\n";
|
||||
parm << " !: Error\n";
|
||||
parm << " V: Verbose\n";
|
||||
parm << " S: Script\n";
|
||||
parm << " a: All (default)\n";
|
||||
parm << "-time_live <sec> : Set runtime time-to-live in seconds.\n";
|
||||
|
||||
return parm;
|
||||
}
|
||||
void ViewerBase::PrintUsage()
|
||||
{
|
||||
std::cout << "Usage: gsviewer input(.nms|.ngp) <-P> <-f|-A> <-S>\n\n";
|
||||
std::cout << GetBaseCommandLineParm() << "\n";
|
||||
PrintAdditionalUsage();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::LocateAndParseBootstrap(Stack <String> &_arg)
|
||||
{
|
||||
SharedPtr <IO::Base> io;
|
||||
AutoPtr <IO::Handle> h;
|
||||
|
||||
// Look for a naked bootstrap file.
|
||||
if ((h = Platform::Get().io->Open("bootstrap.txt")) != NULL)
|
||||
session_source = SessionSourceFilesystem;
|
||||
|
||||
else
|
||||
{
|
||||
// Mount core to default archive.
|
||||
io = new IO::Archive("@root/native/000.gsa");
|
||||
Platform::Get().io->Mount(io, "@core/");
|
||||
|
||||
// Look for an archived bootstrap.
|
||||
h = Platform::Get().io->Open("@core/bootstrap.txt");
|
||||
if (h.IsNull())
|
||||
{
|
||||
Platform::Get().io->Unmount("@core/"); // [EJ] unmount on fail to locate bootstrap
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set archive as the data source.
|
||||
session_source = SessionSourceArchiveBootstrap;
|
||||
Platform::Get().io->Mount(io);
|
||||
}
|
||||
|
||||
// Parse bootstrap.
|
||||
String bootstrap;
|
||||
|
||||
size_t s = h->GetSize();
|
||||
Array <char> s_buffer(s);
|
||||
h->Read(s_buffer, s);
|
||||
|
||||
bootstrap.Set(s_buffer.c_ptr(), &s_buffer.c_ptr()[s]);
|
||||
bootstrap.Split(" ", _arg, '\"');
|
||||
|
||||
h = NULL;
|
||||
return true;
|
||||
}
|
||||
void ViewerBase::SetupVersion(const char *name)
|
||||
{
|
||||
using namespace NML;
|
||||
|
||||
File file;
|
||||
if (!Parser::Load("@root/.reserved/versions.rls", file))
|
||||
return;
|
||||
|
||||
if (Tag *versions = file.GetTag("Versions;"))
|
||||
{
|
||||
NMLTagForeach(v, *versions)
|
||||
if (Tag *n = v->GetTypedTag("Name", Variant::VariantString))
|
||||
if (String(n->GetString()) == name)
|
||||
if (Tag *s = v->GetTypedTag("BootstrapScript", Variant::VariantString))
|
||||
{
|
||||
bootstrap_script = s->GetString();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ViewerBase::ParseCommandLine(Stack <String> &_arg)
|
||||
{
|
||||
if ((_arg.GetCount() < 1) && !LocateAndParseBootstrap(_arg))
|
||||
__ERR__(PrintUsage(), false)
|
||||
|
||||
session_type = SessionScene; // assume scene session
|
||||
|
||||
// Remote is a special flag
|
||||
int n = 0;
|
||||
if (_arg[0] != "-remote")
|
||||
input_path = _arg[n++];
|
||||
|
||||
// Parse optional arguments.
|
||||
int narg = (int)_arg.GetCount();
|
||||
for ( ; n < narg; ++n)
|
||||
{
|
||||
String arg(_arg[n]);
|
||||
|
||||
if (arg == "-P")
|
||||
session_type = SessionProject;
|
||||
|
||||
// Version.
|
||||
else if (arg == "-version")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-version: Missing version name.\n", false);
|
||||
SetupVersion(_arg[n]);
|
||||
}
|
||||
|
||||
// Time to live.
|
||||
else if (arg == "-time_live")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-time_live: Missing mask.\n", false);
|
||||
time_live = String::atoi(_arg[n]);
|
||||
}
|
||||
|
||||
// Log filter.
|
||||
else if (arg == "-log_level")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-log_level: Missing mask.\n", false);
|
||||
|
||||
uint mask = 0;
|
||||
for (const char *p_flag = _arg[n]; p_flag[0]; ++p_flag)
|
||||
switch (p_flag[0])
|
||||
{
|
||||
case 'n': mask = EngineLogNone; break;
|
||||
case 's': mask |= EngineLogStandard; break;
|
||||
case 'H': mask |= EngineLogHeader; break;
|
||||
case '*': mask |= EngineLogWarning; break;
|
||||
case '!': mask |= EngineLogError; break;
|
||||
case 'V': mask |= EngineLogVerbose; break;
|
||||
case 'S': mask |= EngineLogScript; break;
|
||||
case 'a': mask |= EngineLogAll; break;
|
||||
}
|
||||
|
||||
LogSystem::Get().GetLog().SetLogLevel(mask);
|
||||
}
|
||||
|
||||
else if (arg == "-debug")
|
||||
active_debug = true;
|
||||
|
||||
else if (arg == "-ignore_bootstrap")
|
||||
ignore_bootstrap = true;
|
||||
else if (arg == "-ignore_esc")
|
||||
ignore_esc = true;
|
||||
else if (arg == "-ignore_missing")
|
||||
ignore_missing_resource = true;
|
||||
|
||||
else if (arg == "-tool_mode")
|
||||
tool_mode = true;
|
||||
|
||||
else if (arg == "-fallback_disk_fs")
|
||||
Platform::Get().io->Mount(new IO::CFile);
|
||||
|
||||
else if (arg == "-safe_mode")
|
||||
safe_mode = true;
|
||||
|
||||
else if (arg == "-enable_profiler")
|
||||
enable_profiler = true;
|
||||
else if (arg == "-memory_profiler")
|
||||
memory_profiler = true;
|
||||
|
||||
else if (arg == "-enable_pause")
|
||||
enable_pause = true;
|
||||
|
||||
// Config path.
|
||||
else if (arg == "-C")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-C: Missing configuration file path.\n", false);
|
||||
config_path = _arg[n];
|
||||
}
|
||||
|
||||
// File system source.
|
||||
else if (arg == "-f")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-f: Missing root path.\n", false);
|
||||
session_source_path = _arg[n];
|
||||
session_source = SessionSourceFilesystem;
|
||||
}
|
||||
|
||||
// Archive source.
|
||||
else if (arg == "-A")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-A: Missing archive path.\n", false);
|
||||
session_source_path = _arg[n];
|
||||
session_source = SessionSourceArchive;
|
||||
}
|
||||
|
||||
// Renderer.
|
||||
else if (arg == "-r")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-r: Missing renderer id.\n", false);
|
||||
s_render = _arg[n];
|
||||
}
|
||||
|
||||
else if (arg == "-w")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-w: Missing width value.\n", false);
|
||||
width = String::atoi(_arg[n]);
|
||||
}
|
||||
else if (arg == "-h")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-h: Missing height value.\n", false);
|
||||
height = String::atoi(_arg[n]);
|
||||
}
|
||||
|
||||
// Mixer.
|
||||
else if (arg == "-m")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-m: Missing mixer id.\n", false);
|
||||
s_mixer = _arg[n];
|
||||
}
|
||||
|
||||
// Search path.
|
||||
else if (arg == "-S")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-S: Missing search path.\n", false);
|
||||
|
||||
Platform::Get().io->Mount(new IO::CFile(_arg[n]));
|
||||
}
|
||||
|
||||
// Mount core.
|
||||
else if (arg == "-CC")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-CC: Missing core path.\n", false);
|
||||
|
||||
String c_path = _arg[n];
|
||||
Platform::Get().io->Mount(new IO::CFile(c_path), "@core/");
|
||||
Platform::Get().io->Mount(new IO::CFile(c_path)); // FIXME
|
||||
}
|
||||
|
||||
// Mount point.
|
||||
else if (arg == "-MD")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-MD: Missing directory path.\n", false);
|
||||
String dir_path = _arg[n];
|
||||
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-MD: Missing mount point.\n", false);
|
||||
String mount_point = _arg[n];
|
||||
|
||||
Platform::Get().io->Mount(new IO::CFile(dir_path), mount_point);
|
||||
}
|
||||
|
||||
// Raytrace path.
|
||||
else if (arg == "-R")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-R: Missing raytracer output path.\n", false);
|
||||
raytrace_path = _arg[n];
|
||||
}
|
||||
|
||||
// Raytrace width.
|
||||
else if (arg == "-Rw")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-Rw: Missing raytracer frame width.\n", false);
|
||||
raytrace_width = String::atoi(_arg[n]);
|
||||
}
|
||||
|
||||
// Raytrace height.
|
||||
else if (arg == "-Rh")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-Rh: Missing raytracer frame height.\n", false);
|
||||
raytrace_height = String::atoi(_arg[n]);
|
||||
}
|
||||
|
||||
// Raytrace AA.
|
||||
else if (arg == "-Raa")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-Raa: Missing raytracer AA grid size.\n", false);
|
||||
raytrace_aa = String::atoi(_arg[n]);
|
||||
}
|
||||
|
||||
// Include.
|
||||
else if (arg == "-I")
|
||||
{
|
||||
if (++n == narg)
|
||||
__ERR__(__LOG_E__ << "-I: Missing include path.\n", false);
|
||||
|
||||
if (!include_list.Add(_arg[n]))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate include structure.\n", false);
|
||||
}
|
||||
|
||||
// Variable.
|
||||
else if (arg == "-Ds")
|
||||
{
|
||||
n += 2;
|
||||
if (n == narg)
|
||||
__ERR__(__LOG_E__ << "-Ds: Incomplete key-value pair. (eg. -Ds my_var \"String Value\")\n", false);
|
||||
Variant *yo = new Variant(_arg[n - 1], _arg[n]);
|
||||
if (!define_list.Add(new Variant(_arg[n - 1], _arg[n])))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate define structure.\n", false);
|
||||
}
|
||||
|
||||
// Variable.
|
||||
else if (arg == "-Di")
|
||||
{
|
||||
n += 2;
|
||||
if (n == narg)
|
||||
__ERR__(__LOG_E__ << "-Di: Incomplete key-value pair. (eg. -Di my_var 5)\n", false);
|
||||
|
||||
if (!define_list.Add(new Variant(_arg[n - 1], String::atoi(_arg[n]))))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate define structure.\n", false);
|
||||
}
|
||||
|
||||
// Variable.
|
||||
else if (arg == "-Df")
|
||||
{
|
||||
n += 2;
|
||||
if (n == narg)
|
||||
__ERR__(__LOG_E__ << "-Df: Incomplete key-value pair. (eg. -Df my_var 5.5)\n", false);
|
||||
|
||||
if (!define_list.Add(new Variant(_arg[n - 1], String::atof(_arg[n]))))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate define structure.\n", false);
|
||||
}
|
||||
|
||||
else if (!OnUnknownCommandLineParam(_arg, n))
|
||||
__ERR__(__LOG_E__ << "Unknown command line parameter '" << arg << "'\n", false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
33
include/modules/viewer_base/viewer_base_config.cpp
Normal file
33
include/modules/viewer_base/viewer_base_config.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "viewer_base/viewer_base.h"
|
||||
#include "core/renderer.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ViewerBase::LoadViewerConfig(const char *path)
|
||||
{
|
||||
if (!NML::Parser::Load(path, config_file))
|
||||
return false;
|
||||
|
||||
NML::Tag *tag;
|
||||
if ((tag = config_file.GetTypedTag("Fullscreen", Variant::VariantBool)) != NULL)
|
||||
fullscreen = tag->GetBool();
|
||||
if ((tag = config_file.GetTypedTag("Width", Variant::VariantInteger)) != NULL)
|
||||
width = tag->GetInteger();
|
||||
if ((tag = config_file.GetTypedTag("Height", Variant::VariantInteger)) != NULL)
|
||||
height = tag->GetInteger();
|
||||
if ((tag = config_file.GetTypedTag("AspectRatio", Variant::VariantFloat)) != NULL)
|
||||
aspect_ratio = tag->GetReal();
|
||||
|
||||
if (renderer)
|
||||
renderer->SetGlobalAspectRatio(aspect_ratio);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
114
include/modules/viewer_base/viewer_base_debugger.cpp
Normal file
114
include/modules/viewer_base/viewer_base_debugger.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "viewer_base/viewer_base_debugger.h"
|
||||
#include "viewer_base/viewer_base.h"
|
||||
#include "io_net/io_net_client.h"
|
||||
#include "async/task_loop.h"
|
||||
#include "filesystem/io_buffer.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ViewerBaseDebugger::SetViewerStatus(const char *status)
|
||||
{ __LOG__ << "Viewer: " << status << "\n"; }
|
||||
IO::Base *ViewerBaseDebugger::WrapRemoteFileSystem(IO::Base *remote_fs)
|
||||
{ return new IO::Buffer(remote_fs, 65536, 65536); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ViewerBaseDebugger::OnControllerPacketReceived(const Array <char> &data)
|
||||
{
|
||||
using namespace NML;
|
||||
|
||||
Tag tag;
|
||||
Parser::ParseTag(tag, data.Start(), data.End());
|
||||
|
||||
if (tag.name == "ShowPerformanceProfiler")
|
||||
viewer.enable_profiler = tag.GetBool();
|
||||
else if (tag.name == "ShowMemoryProfiler")
|
||||
viewer.memory_profiler = tag.GetBool();
|
||||
else if (tag.name == "DebugPhysics")
|
||||
{
|
||||
if (viewer.project.IsValid())
|
||||
viewer.project->flags.Raise(GS::Core::Project::ProjectFlagDebugPhysics, tag.GetBool());
|
||||
if (viewer.scene_3d.IsValid())
|
||||
viewer.scene_3d->flags.Raise(GS::S3D::Scene::FlagDebugPhysics, tag.GetBool());
|
||||
}
|
||||
|
||||
// Remote session setup.
|
||||
else if (tag.name == "MountRemoteFileSystem")
|
||||
{
|
||||
SetViewerStatus("Connecting to file server");
|
||||
|
||||
String address = GetPeerAddress();
|
||||
|
||||
int port = -1;
|
||||
if (Tag *port_tag = tag.GetTypedTag("Port", GS::Variant::VariantInteger))
|
||||
port = port_tag->GetInteger();
|
||||
|
||||
__LOG_H__ << "Mounting remote file system from " << address << " on port " << port << ".\n";
|
||||
|
||||
if (!address.IsEmpty() && (port != -1))
|
||||
{
|
||||
SharedPtr <IO::Net> net(new IO::Net);
|
||||
|
||||
bool connection_status = false;
|
||||
|
||||
if (net->Connect(address, port))
|
||||
{
|
||||
// Wait for connection...
|
||||
__LOG_H__ << "Waiting for remote file system connection...\n";
|
||||
|
||||
StartTaskLoop(net->IsConnected() == false, 10000) // 10s timeout
|
||||
Platform::Get().Sleep(1);
|
||||
EndTaskLoop
|
||||
|
||||
if ((connection_status = net->IsConnected()) == true)
|
||||
{
|
||||
// Mount net FS through an IO cache layer.
|
||||
viewer.remote_fs = WrapRemoteFileSystem(net);
|
||||
Platform::Get().io->Mount(viewer.remote_fs);
|
||||
|
||||
// Remote FS ready.
|
||||
BroadcastNetworkCommand("<RemoteFileSystemOk>");
|
||||
}
|
||||
}
|
||||
|
||||
if (connection_status == false)
|
||||
SetViewerStatus("File server connection failed");
|
||||
}
|
||||
}
|
||||
else if (tag.name == "SetSessionInput")
|
||||
{
|
||||
SetViewerStatus("Loading session");
|
||||
|
||||
viewer.remote_project.Clear();
|
||||
if (Tag *t = tag.GetTag("Environment"))
|
||||
viewer.remote_project.AddRoot(t->Clone());
|
||||
|
||||
viewer.remote_scene.Clear();
|
||||
if (Tag *t = tag.GetTag("Scene"))
|
||||
viewer.remote_scene.AddRoot(t->Clone());
|
||||
else if (Tag *t = tag.GetTag("Scene2D"))
|
||||
viewer.remote_scene.AddRoot(t->Clone());
|
||||
|
||||
BroadcastNetworkCommand("<SetSessionInputOK>");
|
||||
}
|
||||
else if (tag.name == "StartSession")
|
||||
{
|
||||
SetViewerStatus("Session Running");
|
||||
viewer.state = ViewerBase::SessionSetup; // setup session before starting it
|
||||
}
|
||||
else
|
||||
NetworkDebugger::OnControllerPacketReceived(data);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ViewerBaseDebugger::ViewerBaseDebugger(ViewerBase &v, IDebugger *idbg, const char *address, int port) : NetworkDebugger(v.script_vm, idbg, address, port), viewer(v) {}
|
||||
36
include/modules/viewer_base/viewer_base_vmhook.cpp
Normal file
36
include/modules/viewer_base/viewer_base_vmhook.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "viewer_base/viewer_base_vmhook.h"
|
||||
#include "viewer_base/viewer_base.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Script;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ViewerEventHookTable::OnStep(char type, const char *source, int line, const char *funcname)
|
||||
{}
|
||||
void ViewerEventHookTable::Kill(const char *reason)
|
||||
{ viewer->DisplayUserMessage(ViewerBase::MessageWarning, String::Format("The script VM was killed:\n\n%s", reason)); }
|
||||
void ViewerEventHookTable::OnCompilerError(const char *error, const char *source, int line)
|
||||
{ viewer->DisplayUserMessage(ViewerBase::MessageNormal, String::Format("Script compiler error.\n\nSource: %s\nLine: %d\n\n%s", source, line, error)); }
|
||||
void ViewerEventHookTable::OnRuntimeException(const char *error)
|
||||
{
|
||||
String msg = String::Format("Script runtime exception:\n\n%s", error);
|
||||
|
||||
AutoList <IVM::CallStackEntry *> callstack;
|
||||
viewer->project->vm->GetCallStack(callstack);
|
||||
|
||||
msg += "\n\nCallstack:\n\n";
|
||||
ListForeachPtr(IVM::CallStackEntry *, cs, callstack)
|
||||
msg += String::Format(" - %s() (line %d) in \"%s\"\n", cs->function.c_str(), cs->line, cs->source.c_str());
|
||||
|
||||
__LOG_E__ << "Squirrel Compiler Error: '" << msg << "'\n";
|
||||
|
||||
viewer->DisplayUserMessage(ViewerBase::MessageNormal, msg);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user