commit x64 compilation from lulu cause the other branch dont seems to compile properly at home

This commit is contained in:
2026-07-17 16:08:20 +02:00
parent c0f3eeb00d
commit 0efa4ee6f7
625 changed files with 117283 additions and 4426 deletions

View 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();
}
//------------------------------------------------------------------------------

View 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(); }
//------------------------------------------------------------------------------

View File

@ -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();
}
//------------------------------------------------------------------------------

View 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);
}
//------------------------------------------------------------------------------

View 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();
}
//------------------------------------------------------------------------------

View 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); }

View 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); }
//------------------------------------------------------------------------------

View 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);
}
//------------------------------------------------------------------------------

View 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();
}
//------------------------------------------------------------------------------

View 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();
}
//------------------------------------------------------------------------------

View 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";
}

View 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); }
//------------------------------------------------------------------------------

View 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) {}
//------------------------------------------------------------------------------

View 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(); }
//------------------------------------------------------------------------------

View 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();
}
//------------------------------------------------------------------------------

View 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); }
//------------------------------------------------------------------------------

View 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(&params, 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(&params, &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;
}
//------------------------------------------------------------------------------

View 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();
}
//------------------------------------------------------------------------------

View 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);
}
//------------------------------------------------------------------------------

View 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();
}
//------------------------------------------------------------------------------

View 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;
}

View 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();
}
//----------------------------------------------------------------------------------

View 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();
}
//------------------------------------------------------------------------------

View 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;
}
//------------------------------------------------------------------------------

View 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());
}
//-----------------------------------------------------------------------------

View 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;
}

View 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;
}
//------------------------------------------------------------------------------

View 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);
}
}
//------------------------------------------------------------------------------

View 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;
}
//------------------------------------------------------------------------------

View 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();
}
//------------------------------------------------------------------------------

View 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();
}
//------------------------------------------------------------------------------

View 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;
}
//------------------------------------------------------------------------------

View 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();
}
//------------------------------------------------------------------------------

View 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)
//------------------------------------------------------------------------------

View File

@ -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__

View 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)

View 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)

View File

@ -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;
}

View 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);
}

View 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)
}
//------------------------------------------------------------------------------

View 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)
//------------------------------------------------------------------------------

View 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);
}

View 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();
}
//------------------------------------------------------------------------------

View 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) {}

View 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;

View 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
#*/
}

View 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);
}

View 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);
}

View 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"));
}
//------------------------------------------------------------------------------

View 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);
}

View 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"));
}

View 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"));
}
//------------------------------------------------------------------------------

View 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"));
}

View 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"));
}

View 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"));
}

View 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&amp;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("."));
}

View 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"));
}
//------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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);
}
//------------------------------------------------------------------------------

View 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);
}
//------------------------------------------------------------------------------

View File

@ -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"));
}
//------------------------------------------------------------------------------

View 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"));
}
//------------------------------------------------------------------------------

View 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);
}
//------------------------------------------------------------------------------

View 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);
}
//------------------------------------------------------------------------------

View 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);
}
//-----------------------------------------------------------------------------

View 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"));
}
//------------------------------------------------------------------------------

View 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"));
}
//------------------------------------------------------------------------------

View 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);
}
//------------------------------------------------------------------------------

View 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);
}

View 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("."));
}
//------------------------------------------------------------------------------

View 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("."));
}

View 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);
}
//------------------------------------------------------------------------------

View 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"));
}
//------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -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"));
}
//------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View 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"));
}
//------------------------------------------------------------------------------

View 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);
}

View File

@ -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);

View 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);
}
//------------------------------------------------------------------------------

View 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);
}
//------------------------------------------------------------------------------

View 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"));
}
//------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View 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

View 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);
}

View 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;
}
//------------------------------------------------------------------------------

View 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);
}
}
//------------------------------------------------------------------------------

View 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();
}

View 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();
}
//------------------------------------------------------------------------------

View 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;
}
//------------------------------------------------------------------------------

View 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();
}
//------------------------------------------------------------------------------

View 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;
}
//------------------------------------------------------------------------------

View 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;
}
//------------------------------------------------------------------------------

View 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;
}
//-----------------------------------------------------------------------------

View 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;
}
//------------------------------------------------------------------------------

View 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) {}

View 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);
}
//------------------------------------------------------------------------------