Finished refactoring angelscript internal api

This commit is contained in:
Chewico 2026-01-14 17:56:41 +01:00
parent 47871fa1dc
commit 54f8156b6b
18 changed files with 2005 additions and 1890 deletions

View File

@ -8,7 +8,7 @@ namespace Deer {
void Log::init() {
// spdlog::set_pattern("%^[%T] %n: %v%$");
spdlog::set_pattern("%n: %v%$");
spdlog::set_pattern("%v%$");
coreLogger = spdlog::stdout_color_mt("Core");
clientLogger = spdlog::stdout_color_mt("Client");

View File

@ -28,14 +28,12 @@
andreas@angelcode.com
*/
//
// angelscript.h
//
// The script engine interface
//
#ifndef ANGELSCRIPT_H
#define ANGELSCRIPT_H
@ -115,8 +113,7 @@ typedef __int64 asINT64;
// Enumerations and constants
// Return codes
enum asERetCodes
{
enum asERetCodes {
asSUCCESS = 0,
asERROR = -1,
asCONTEXT_ACTIVE = -2,
@ -149,8 +146,7 @@ enum asERetCodes
};
// Engine properties
enum asEEngineProp
{
enum asEEngineProp {
asEP_ALLOW_UNSAFE_REFERENCES = 1,
asEP_OPTIMIZE_BYTECODE = 2,
asEP_COPY_SCRIPT_SECTIONS = 3,
@ -195,8 +191,7 @@ enum asEEngineProp
};
// Calling conventions
enum asECallConvTypes
{
enum asECallConvTypes {
asCALL_CDECL = 0,
asCALL_STDCALL = 1,
asCALL_THISCALL_ASGLOBAL = 2,
@ -209,8 +204,7 @@ enum asECallConvTypes
};
// Object type flags
enum asEObjTypeFlags : asQWORD
{
enum asEObjTypeFlags : asQWORD {
asOBJ_REF = (1 << 0),
asOBJ_VALUE = (1 << 1),
asOBJ_GC = (1 << 2),
@ -264,8 +258,7 @@ enum asEObjTypeFlags : asQWORD
};
// Behaviours
enum asEBehaviours
{
enum asEBehaviours {
// Value object memory management
asBEHAVE_CONSTRUCT,
asBEHAVE_LIST_CONSTRUCT,
@ -294,8 +287,7 @@ enum asEBehaviours
};
// Context states
enum asEContextState
{
enum asEContextState {
asEXECUTION_FINISHED = 0,
asEXECUTION_SUSPENDED = 1,
asEXECUTION_ABORTED = 2,
@ -308,16 +300,14 @@ enum asEContextState
};
// Message types
enum asEMsgType
{
enum asEMsgType {
asMSGTYPE_ERROR = 0,
asMSGTYPE_WARNING = 1,
asMSGTYPE_INFORMATION = 2
};
// Garbage collector flags
enum asEGCFlags
{
enum asEGCFlags {
asGC_FULL_CYCLE = 1,
asGC_ONE_STEP = 2,
asGC_DESTROY_GARBAGE = 4,
@ -325,8 +315,7 @@ enum asEGCFlags
};
// Token classes
enum asETokenClass
{
enum asETokenClass {
asTC_UNKNOWN = 0,
asTC_KEYWORD = 1,
asTC_VALUE = 2,
@ -336,8 +325,7 @@ enum asETokenClass
};
// Type id flags
enum asETypeIdFlags
{
enum asETypeIdFlags {
asTYPEID_VOID = 0,
asTYPEID_BOOL = 1,
asTYPEID_INT8 = 2,
@ -360,8 +348,7 @@ enum asETypeIdFlags
};
// Type modifiers
enum asETypeModifiers
{
enum asETypeModifiers {
asTM_NONE = 0,
asTM_INREF = 1,
asTM_OUTREF = 2,
@ -370,22 +357,19 @@ enum asETypeModifiers
};
// GetModule flags
enum asEGMFlags
{
enum asEGMFlags {
asGM_ONLY_IF_EXISTS = 0,
asGM_CREATE_IF_NOT_EXISTS = 1,
asGM_ALWAYS_CREATE = 2
};
// Compile flags
enum asECompileFlags
{
enum asECompileFlags {
asCOMP_ADD_TO_MODULE = 1
};
// Function types
enum asEFuncType
{
enum asEFuncType {
asFUNC_DUMMY = -1,
asFUNC_SYSTEM = 0,
asFUNC_SCRIPT = 1,
@ -452,29 +436,31 @@ typedef void (*asJITFunction)(asSVMRegisters* registers, asPWORD jitArg);
class asCUnknownClass;
typedef void (asCUnknownClass::*asMETHOD_t)();
struct asSFuncPtr
{
asSFuncPtr(asBYTE f = 0)
{
struct asSFuncPtr {
asSFuncPtr(asBYTE f = 0) {
for (size_t n = 0; n < sizeof(ptr.dummy); n++)
ptr.dummy[n] = 0;
flag = f;
}
void CopyMethodPtr(const void *mthdPtr, size_t size)
{
void CopyMethodPtr(const void* mthdPtr, size_t size) {
for (size_t n = 0; n < size; n++)
ptr.dummy[n] = reinterpret_cast<const char*>(mthdPtr)[n];
}
union
{
union {
// The largest known method point is 20 bytes (MSVC 64bit),
// but with 8byte alignment this becomes 24 bytes. So we need
// to be able to store at least that much.
char dummy[25];
struct {asMETHOD_t mthd; char dummy[25-sizeof(asMETHOD_t)];} m;
struct {asFUNCTION_t func; char dummy[25-sizeof(asFUNCTION_t)];} f;
struct {
asMETHOD_t mthd;
char dummy[25 - sizeof(asMETHOD_t)];
} m;
struct {
asFUNCTION_t func;
char dummy[25 - sizeof(asFUNCTION_t)];
} f;
} ptr;
asBYTE flag; // 1 = generic, 2 = global func, 3 = method
};
@ -490,8 +476,7 @@ struct asSFuncPtr
#define AS_METHOD_AMBIGUITY_CAST(t) (t)
#else
template <typename T>
T _implicit_cast (T val)
{ return val; }
T _implicit_cast(T val) { return val; }
#define AS_METHOD_AMBIGUITY_CAST(t) AS_NAMESPACE_QUALIFIER _implicit_cast<t>
#endif
#else
@ -503,27 +488,26 @@ template <typename T>
#else // Class methods are disabled
struct asSFuncPtr
{
asSFuncPtr(asBYTE f)
{
struct asSFuncPtr {
asSFuncPtr(asBYTE f) {
for (size_t n = 0; n < sizeof(ptr.dummy); n++)
ptr.dummy[n] = 0;
flag = f;
}
union
{
union {
char dummy[25]; // largest known class method pointer
struct {asFUNCTION_t func; char dummy[25-sizeof(asFUNCTION_t)];} f;
struct {
asFUNCTION_t func;
char dummy[25 - sizeof(asFUNCTION_t)];
} f;
} ptr;
asBYTE flag; // 1 = generic, 2 = global func
};
#endif
struct asSMessageInfo
{
struct asSMessageInfo {
const char* section;
int row;
int col;
@ -531,7 +515,6 @@ struct asSMessageInfo
const char* message;
};
// API functions
// ANGELSCRIPT_EXPORT is defined when compiling the dll or lib
@ -559,8 +542,7 @@ struct asSMessageInfo
#endif
#ifndef ANGELSCRIPT_DLL_MANUAL_IMPORT
extern "C"
{
extern "C" {
// Engine
AS_API asIScriptEngine* asCreateScriptEngine(asDWORD version = ANGELSCRIPT_VERSION);
AS_API const char* asGetLibraryVersion();
@ -601,8 +583,7 @@ END_AS_NAMESPACE
BEGIN_AS_NAMESPACE
template <typename T>
asUINT asGetTypeTraits()
{
asUINT asGetTypeTraits() {
#if defined(_MSC_VER) || defined(_LIBCPP_TYPE_TRAITS) || (__GNUC__ >= 5) || (defined(__clang__) && !defined(CLANG_PRE_STANDARD))
// MSVC, XCode/Clang, and gnuc 5+
// C++11 compliant code
@ -637,8 +618,7 @@ asUINT asGetTypeTraits()
if (isPrimitive)
return asOBJ_APP_PRIMITIVE;
if( isClass )
{
if (isClass) {
asDWORD flags = asOBJ_APP_CLASS;
if (hasConstructor)
flags |= asOBJ_APP_CLASS_CONSTRUCTOR;
@ -662,8 +642,7 @@ asUINT asGetTypeTraits()
// Interface declarations
class asIScriptEngine
{
class asIScriptEngine {
public:
// Memory management
virtual int AddRef() const = 0;
@ -807,8 +786,7 @@ protected:
virtual ~asIScriptEngine() {}
};
class asIStringFactory
{
class asIStringFactory {
public:
virtual const void* GetStringConstant(const char* data, asUINT length) = 0;
virtual int ReleaseStringConstant(const void* str) = 0;
@ -818,14 +796,12 @@ protected:
virtual ~asIStringFactory() {}
};
class asIThreadManager
{
class asIThreadManager {
protected:
virtual ~asIThreadManager() {}
};
class asIScriptModule
{
class asIScriptModule {
public:
virtual asIScriptEngine* GetEngine() const = 0;
virtual void SetName(const char* name) = 0;
@ -895,8 +871,7 @@ protected:
virtual ~asIScriptModule() {}
};
class asIScriptContext
{
class asIScriptContext {
public:
// Memory management
virtual int AddRef() const = 0;
@ -993,8 +968,7 @@ protected:
virtual ~asIScriptContext() {}
};
class asIScriptGeneric
{
class asIScriptGeneric {
public:
// Miscellaneous
virtual asIScriptEngine* GetEngine() const = 0;
@ -1034,8 +1008,7 @@ protected:
virtual ~asIScriptGeneric() {}
};
class asIScriptObject
{
class asIScriptObject {
public:
// Memory management
virtual int AddRef() const = 0;
@ -1064,8 +1037,7 @@ protected:
virtual ~asIScriptObject() {}
};
class asITypeInfo
{
class asITypeInfo {
public:
// Miscellaneous
virtual asIScriptEngine* GetEngine() const = 0;
@ -1137,8 +1109,7 @@ protected:
virtual ~asITypeInfo() {}
};
class asIScriptFunction
{
class asIScriptFunction {
public:
virtual asIScriptEngine* GetEngine() const = 0;
@ -1208,8 +1179,7 @@ protected:
virtual ~asIScriptFunction() {};
};
class asIBinaryStream
{
class asIBinaryStream {
public:
virtual int Read(void* ptr, asUINT size) = 0;
virtual int Write(const void* ptr, asUINT size) = 0;
@ -1218,8 +1188,7 @@ public:
virtual ~asIBinaryStream() {}
};
class asILockableSharedBool
{
class asILockableSharedBool {
public:
// Memory management
virtual int AddRef() const = 0;
@ -1243,8 +1212,7 @@ protected:
// Template function to capture all global functions,
// except the ones using the generic calling convention
template <class T>
inline asSFuncPtr asFunctionPtr(T func)
{
inline asSFuncPtr asFunctionPtr(T func) {
// Mark this as a global function
asSFuncPtr p(2);
@ -1263,8 +1231,7 @@ inline asSFuncPtr asFunctionPtr(T func)
// Specialization for functions using the generic calling convention
template <>
inline asSFuncPtr asFunctionPtr<asGENFUNC_t>(asGENFUNC_t func)
{
inline asSFuncPtr asFunctionPtr<asGENFUNC_t>(asGENFUNC_t func) {
// Mark this as a generic function
asSFuncPtr p(1);
p.ptr.f.func = reinterpret_cast<asFUNCTION_t>(func);
@ -1282,11 +1249,9 @@ const int SINGLE_PTR_SIZE = sizeof(asSIMPLEMETHOD_t);
// Define template
template <int N>
struct asSMethodPtr
{
struct asSMethodPtr {
template <class M>
static asSFuncPtr Convert(M Mthd)
{
static asSFuncPtr Convert(M Mthd) {
// This version of the function should never be executed, nor compiled,
// as it would mean that the size of the method pointer cannot be determined.
@ -1299,11 +1264,9 @@ struct asSMethodPtr
// Template specialization
template <>
struct asSMethodPtr<SINGLE_PTR_SIZE>
{
struct asSMethodPtr<SINGLE_PTR_SIZE> {
template <class M>
static asSFuncPtr Convert(M Mthd)
{
static asSFuncPtr Convert(M Mthd) {
// Mark this as a class method
asSFuncPtr p(3);
p.CopyMethodPtr(&Mthd, SINGLE_PTR_SIZE);
@ -1315,11 +1278,9 @@ struct asSMethodPtr<SINGLE_PTR_SIZE>
// MSVC and Intel uses different sizes for different class method pointers
template <>
struct asSMethodPtr<SINGLE_PTR_SIZE+1*sizeof(int)>
{
struct asSMethodPtr<SINGLE_PTR_SIZE + 1 * sizeof(int)> {
template <class M>
static asSFuncPtr Convert(M Mthd)
{
static asSFuncPtr Convert(M Mthd) {
// Mark this as a class method
asSFuncPtr p(3);
p.CopyMethodPtr(&Mthd, SINGLE_PTR_SIZE + sizeof(int));
@ -1328,11 +1289,9 @@ struct asSMethodPtr<SINGLE_PTR_SIZE+1*sizeof(int)>
};
template <>
struct asSMethodPtr<SINGLE_PTR_SIZE+2*sizeof(int)>
{
struct asSMethodPtr<SINGLE_PTR_SIZE + 2 * sizeof(int)> {
template <class M>
static asSFuncPtr Convert(M Mthd)
{
static asSFuncPtr Convert(M Mthd) {
// On 32bit platforms with is where a class with virtual inheritance falls.
// On 64bit platforms we can also fall here if 8byte data alignments is used.
@ -1358,7 +1317,6 @@ struct asSMethodPtr<SINGLE_PTR_SIZE+2*sizeof(int)>
// This will force the compiler to use the unknown type
// for the class, which falls under the next case
// Copy the virtual table index to the 4th dword so that AngelScript
// can properly detect and deny the use of methods with virtual inheritance.
*(reinterpret_cast<asDWORD*>(&p) + 3) = *(reinterpret_cast<asDWORD*>(&p) + 2);
@ -1369,11 +1327,9 @@ struct asSMethodPtr<SINGLE_PTR_SIZE+2*sizeof(int)>
};
template <>
struct asSMethodPtr<SINGLE_PTR_SIZE+3*sizeof(int)>
{
struct asSMethodPtr<SINGLE_PTR_SIZE + 3 * sizeof(int)> {
template <class M>
static asSFuncPtr Convert(M Mthd)
{
static asSFuncPtr Convert(M Mthd) {
// Mark this as a class method
asSFuncPtr p(3);
p.CopyMethodPtr(&Mthd, SINGLE_PTR_SIZE + 3 * sizeof(int));
@ -1382,11 +1338,9 @@ struct asSMethodPtr<SINGLE_PTR_SIZE+3*sizeof(int)>
};
template <>
struct asSMethodPtr<SINGLE_PTR_SIZE+4*sizeof(int)>
{
struct asSMethodPtr<SINGLE_PTR_SIZE + 4 * sizeof(int)> {
template <class M>
static asSFuncPtr Convert(M Mthd)
{
static asSFuncPtr Convert(M Mthd) {
// On 64bit platforms with 8byte data alignment
// the unknown class method pointers will come here.
@ -1404,8 +1358,7 @@ struct asSMethodPtr<SINGLE_PTR_SIZE+4*sizeof(int)>
//----------------------------------------------------------------
// JIT compiler
struct asSVMRegisters
{
struct asSVMRegisters {
asDWORD* programPointer; // points to current bytecode instruction
asDWORD* stackFramePointer; // function stack frame
asDWORD* stackPointer; // top of stack (grows downward)
@ -1416,35 +1369,33 @@ struct asSVMRegisters
asIScriptContext* ctx; // the active context
};
class asIJITCompilerAbstract
{
class asIJITCompilerAbstract {
public:
virtual ~asIJITCompilerAbstract() {}
};
// JIT Compiler interface version 1
class asIJITCompiler : public asIJITCompilerAbstract
{
class asIJITCompiler : public asIJITCompilerAbstract {
public:
virtual int CompileFunction(asIScriptFunction* function, asJITFunction* output) = 0;
virtual void ReleaseJITFunction(asJITFunction func) = 0;
public:
virtual ~asIJITCompiler() {}
};
// JIT Compiler interface version 2
class asIJITCompilerV2 : public asIJITCompilerAbstract
{
class asIJITCompilerV2 : public asIJITCompilerAbstract {
public:
virtual void NewFunction(asIScriptFunction* scriptFunc) = 0;
virtual void CleanFunction(asIScriptFunction* scriptFunc, asJITFunction jitFunc) = 0;
public:
virtual ~asIJITCompilerV2() {}
};
// Byte code instructions
enum asEBCInstr
{
enum asEBCInstr {
asBC_PopPtr = 0,
asBC_PshGPtr = 1,
asBC_PshC4 = 2,
@ -1658,8 +1609,7 @@ enum asEBCInstr
};
// Instruction types
enum asEBCType
{
enum asEBCType {
asBCTYPE_INFO = 0,
asBCTYPE_NO_ARG = 1,
asBCTYPE_W_ARG = 2,
@ -1710,8 +1660,7 @@ const int asBCTypeSize[21] =
};
// Instruction info
struct asSBCInfo
{
struct asSBCInfo {
asEBCInstr bc;
asEBCType type;
int stackInc;
@ -1998,8 +1947,7 @@ const asSBCInfo asBCInfo[256] =
asBCINFO(Block, INFO, 0),
asBCINFO(ObjInfo, rW_DW_ARG, 0),
asBCINFO(LINE, INFO, 0),
asBCINFO(LABEL, INFO, 0)
};
asBCINFO(LABEL, INFO, 0)};
// Macros to access bytecode instruction arguments
#define asBC_DWORDARG(x) (*(((asDWORD*)x) + 1))
@ -2013,7 +1961,6 @@ const asSBCInfo asBCInfo[256] =
#define asBC_SWORDARG1(x) (*(((short*)x) + 2))
#define asBC_SWORDARG2(x) (*(((short*)x) + 3))
END_AS_NAMESPACE
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
#pragma once
#include "DeerRender/Tools/Memory.h"
#include "DeerRender/Tools/Path.h"
#include <string>
#include <unordered_map>
@ -9,8 +10,10 @@ class asIScriptModule;
class asIScriptContext;
class asIScriptObject;
class asIScriptFunction;
class asIScriptFunction;
class asITypeInfo;
class CScriptBuilder;
class asIScriptGeneric;
namespace Deer {
namespace AngelScriptEngine {
@ -20,6 +23,12 @@ namespace Deer {
void render();
void deinitialize();
struct ServiceExposedFunctionData {
asIScriptFunction* exposedFunction = nullptr;
asIScriptObject* exposedObject = nullptr;
std::string exposedFunctionName;
};
struct Service {
public:
Service(asITypeInfo*);
@ -34,14 +43,25 @@ namespace Deer {
void update();
void shutdown();
void updateTypes(asIScriptModule*);
void registerApiExpose();
protected:
asITypeInfo* type = nullptr;
asIScriptObject* object = nullptr;
asIScriptFunction* updateFunction = nullptr;
asIScriptFunction* initFunction = nullptr;
asIScriptFunction* shutdownFunction = nullptr;
std::vector<Scope<ServiceExposedFunctionData>> exposedFunctions;
std::string typeName;
private:
void registerExposedFunction(asIScriptFunction*);
};
void service_exposed_generic_call(asIScriptGeneric*);
struct Panel : public Service {
public:
Panel(asITypeInfo*);
@ -52,6 +72,7 @@ namespace Deer {
Panel& operator=(Panel&&) = default;
void render();
void updateTypes(asIScriptModule*);
private:
asIScriptFunction* renderFunction;
@ -93,7 +114,8 @@ namespace Deer {
void render();
void shutdown();
void extractTypes();
void extract(asIScriptModule*);
void updateTypes();
inline void invalidate() { state = ModuleState::ExecutionError; }

View File

@ -7,27 +7,45 @@ namespace Deer {
namespace AngelScriptEngine {
Module::Module(const ModuleDescription& _mi) : moduleInfo(_mi) {}
void Module::extractTypes() {
void Module::extract(asIScriptModule* _module) {
if (state != ModuleState::Built)
return;
angelscriptModule = AngelScriptEngine::scriptEngine->GetModule(moduleInfo.moduleName.c_str());
uint32_t typeCount = angelscriptModule->GetObjectTypeCount();
angelscriptModule = _module;
scriptEngine->SetDefaultNamespace(moduleInfo.moduleName.c_str());
uint32_t typeCount = angelscriptModule->GetObjectTypeCount();
for (uint32_t typeId = 0; typeId < typeCount; typeId++) {
asITypeInfo* typeInfo = angelscriptModule->GetObjectTypeByIndex(typeId);
if (ImplementsInterface(typeInfo, serviceBaseType)) {
services.push_back({typeInfo});
services.back().registerApiExpose();
} else if (ImplementsInterface(typeInfo, panelBaseType)) {
panels.push_back({typeInfo});
panels.back().registerApiExpose();
}
}
scriptEngine->SetDefaultNamespace("");
}
void Module::updateTypes() {
if (state != ModuleState::Built)
return;
angelscriptModule = AngelScriptEngine::scriptEngine->GetModule(moduleInfo.moduleName.c_str());
for (Service& service : services)
service.updateTypes(angelscriptModule);
for (Panel& panel : panels)
panel.updateTypes(angelscriptModule);
}
void Module::init() {
if (state != ModuleState::Built)
return;
angelscriptModule->BindAllImportedFunctions();
for (Service& service : services)

View File

@ -44,10 +44,12 @@ namespace Deer {
}
bool AngelScriptEngine::loadModule(Module& module) {
if (module.state != ModuleState::NotBuilt)
return false;
int err;
module.state = ModuleState::Building;
DEER_CORE_TRACE("Loading module {}", module.moduleInfo.moduleName);
for (const std::string& dependency : module.moduleInfo.module_requires) {
if (!module_id.contains(dependency)) {
DEER_CORE_ERROR("Failed to find dependency {} for module {}",
@ -79,6 +81,7 @@ namespace Deer {
}
}
}
DEER_CORE_TRACE("Loading module {}", module.moduleInfo.moduleName);
scriptBuilder.StartNewModule(scriptEngine, module.moduleInfo.moduleName.c_str());
if (err < 0) {
@ -109,6 +112,8 @@ namespace Deer {
}
module.state = ModuleState::Built;
module.extract(as_module);
return true;
}
@ -151,12 +156,16 @@ namespace Deer {
desc.modulePath = path.string();
if (module_id.contains(desc.moduleName)) {
DEER_CORE_ERROR("Module name duplicated {}", path.string().c_str());
return;
}
module_id[desc.moduleName] = modules.size();
modules.push_back({desc});
}
void AngelScriptEngine::loadModules() {
generateAngelscriptPredefined();
const Path path = Path("Editor") / Path("Modules");
if (!fs::exists(path) || !fs::is_directory(path)) {
@ -173,14 +182,15 @@ namespace Deer {
}
for (Module& module : modules) {
saveAngelscriptPredefined(module.moduleInfo.modulePath);
if (module.state == ModuleState::NotBuilt) {
loadModule(module);
generateAngelscriptPredefined();
}
saveAngelscriptPredefined(module.moduleInfo.modulePath);
}
for (Module& module : modules) {
module.extractTypes();
module.updateTypes();
}
}
} // namespace Deer

View File

@ -12,6 +12,13 @@ namespace Deer {
menuBarFunction = type->GetMethodByDecl("void menuBar()");
}
void Panel::updateTypes(asIScriptModule* typeInfo) {
Service::updateTypes(typeInfo);
renderFunction = type->GetMethodByDecl("void render()");
menuBarFunction = type->GetMethodByDecl("void menuBar()");
}
void Panel::render() {
// IMPLEMENT REMOVE PADDING
if (menuBarFunction) {

View File

@ -4,6 +4,7 @@
// https://github.com/sashi0034/angel-lsp/blob/main/examples/OpenSiv3D/make_predefined.cpp
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "DeerRender/Log.h"
#include "DeerStudio/AngelScriptEngine.h"
#include "angelscript.h"
@ -71,6 +72,43 @@ void printEnumList(const asIScriptEngine& engine) {
}
}
void writeParameters(asIScriptFunction* function) {
for (int n = 0; n < function->GetParamCount(); n++) {
int typeId;
asDWORD flags;
const char* name;
const char* defaultArgument;
function->GetParam(n, &typeId, &flags, &name, &defaultArgument);
if (typeId == -1) {
stream << "?";
} else {
asITypeInfo* ti = function->GetEngine()->GetTypeInfoById(typeId);
if (ti && (ti->GetFlags() & asOBJ_FUNCDEF)) {
stream << ti->GetName();
} else {
const char* typeName = function->GetEngine()->GetTypeDeclaration(typeId, false);
stream << typeName;
}
}
if (flags & asTM_INREF)
stream << " &in ";
else if (flags & asTM_OUTREF)
stream << " &out ";
else if (flags & asTM_INOUTREF)
stream << " &inout ";
if (name) {
stream << " " << name;
}
if (n != function->GetParamCount() - 1)
stream << ", ";
}
}
void printClassTypeList(const asIScriptEngine& engine) {
for (int i = 0; i < engine.GetObjectTypeCount(); ++i) {
asITypeInfo* t = engine.GetObjectTypeByIndex(i);
@ -109,7 +147,9 @@ void printClassTypeList(const asIScriptEngine& engine) {
for (int j = 0; j < t->GetFactoryCount(); ++j) {
asIScriptFunction* f = t->GetFactoryByIndex(j);
stream << "\t" << f->GetDeclaration(false, false, true) << ";\n";
stream << "\t" << t->GetName() << "(";
writeParameters(f);
stream << ");\n";
}
for (int j = 0; j < t->GetBehaviourCount(); ++j) {
@ -125,7 +165,21 @@ void printClassTypeList(const asIScriptEngine& engine) {
for (int j = 0; j < t->GetMethodCount(); ++j) {
const auto m = t->GetMethodByIndex(j);
stream << "\t" << m->GetDeclaration(false, false, true);
stream << "\t";
int methodReturnId = m->GetReturnTypeId();
if (methodReturnId == -1) {
stream << "? ";
} else {
stream << t->GetEngine()->GetTypeDeclaration(methodReturnId) << " ";
}
stream << m->GetName() << "(";
writeParameters(m);
stream << ")";
// stream << "\t" << m->GetDeclaration(false, false, true);
if (m->IsProperty())
stream << " property";

View File

@ -1,8 +1,11 @@
#include "DeerStudio/AngelScriptEngine.h"
#include "DeerStudio/AngelScriptEngine/ErrorHandle.h"
#include "angelscript.h"
#include "scriptbuilder.h"
#include <cstring>
#include <string>
#include <vector>
namespace Deer {
namespace AngelScriptEngine {
@ -27,6 +30,11 @@ namespace Deer {
object->AddRef();
AS_CHECK(scriptContext->Unprepare());
for (Scope<ServiceExposedFunctionData>& exposedFunction : exposedFunctions) {
exposedFunction->exposedFunction = type->GetMethodByName(exposedFunction->exposedFunctionName.c_str());
exposedFunction->exposedObject = object;
}
if (!initFunction)
return;
@ -37,6 +45,214 @@ namespace Deer {
AS_CHECK(scriptContext->Unprepare());
}
void Service::registerApiExpose() {
int functionCount = type->GetMethodCount();
for (int i = 0; i < functionCount; i++) {
asIScriptFunction* function = type->GetMethodByIndex(i);
bool containsExposeMetadata = false;
std::vector<std::string> metadata = scriptBuilder.GetMetadataForTypeMethod(type->GetTypeId(), function);
for (std::string& meta : metadata) {
if (meta == "Expose") {
containsExposeMetadata = true;
break;
}
}
if (!containsExposeMetadata)
continue;
registerExposedFunction(function);
}
}
void Service::registerExposedFunction(asIScriptFunction* function) {
asITypeInfo* returnType = scriptEngine->GetTypeInfoById(function->GetReturnTypeId());
if (returnType && returnType->GetModule()) {
DEER_CORE_ERROR("Error registering function {}, you can not register engine non specific type for return type", function->GetDeclaration());
return;
}
std::string declaration;
declaration = scriptEngine->GetTypeDeclaration(function->GetReturnTypeId(), false);
declaration += " ";
declaration += function->GetName();
declaration += "(";
int paramCount = function->GetParamCount();
for (int n = 0; n < paramCount; n++) {
int typeId;
asDWORD flags;
const char* name;
const char* defaultArgument;
function->GetParam(n, &typeId, &flags, &name, &defaultArgument);
asITypeInfo* paramType = scriptEngine->GetTypeInfoById(typeId);
if (paramType && paramType->GetModule()) {
DEER_CORE_ERROR("Error registering function {}, you can not register engine non specific type in parameter", function->GetDeclaration());
return;
}
const char* typeName = scriptEngine->GetTypeDeclaration(typeId, false);
declaration += typeName;
if (flags & asTM_INREF)
declaration += " in ";
else if (flags & asTM_OUTREF)
declaration += " out ";
else if (flags & asTM_INOUTREF)
declaration += " inout ";
if (name) {
declaration += " ";
declaration += name;
}
if (defaultArgument) {
declaration += "= ";
declaration += defaultArgument;
}
if (n != paramCount - 1)
declaration += ", ";
}
declaration += ")";
exposedFunctions.push_back(MakeScope<ServiceExposedFunctionData>());
ServiceExposedFunctionData* exposedFunctionData = exposedFunctions.back().get();
exposedFunctionData->exposedFunction = function;
exposedFunctionData->exposedFunctionName = function->GetName();
exposedFunctionData->exposedObject = object;
DEER_CORE_TRACE("Registering {}", declaration.c_str());
scriptEngine->RegisterGlobalFunction(declaration.c_str(), asFUNCTION(service_exposed_generic_call), asCALL_GENERIC, exposedFunctionData);
}
void service_exposed_generic_call(asIScriptGeneric* genericFun) {
AS_CHECK(scriptContext->PushState());
ServiceExposedFunctionData* data = (ServiceExposedFunctionData*)genericFun->GetAuxiliary();
AS_CHECK(scriptContext->Prepare(data->exposedFunction));
AS_CHECK(scriptContext->SetObject(data->exposedObject));
int argCount = genericFun->GetArgCount();
for (int i = 0; i < argCount; ++i) {
int typeId = genericFun->GetArgTypeId(i);
if (typeId & asTYPEID_OBJHANDLE) {
void* obj = genericFun->GetAddressOfArg(i);
AS_CHECK(scriptContext->SetArgAddress(i, obj));
} else if (typeId & asTYPEID_MASK_OBJECT) {
void* obj = genericFun->GetArgObject(i);
AS_CHECK(scriptContext->SetArgObject(i, obj));
} else {
switch (typeId) {
case asTYPEID_BOOL:
case asTYPEID_INT8:
case asTYPEID_UINT8:
AS_CHECK(scriptContext->SetArgByte(i, genericFun->GetArgByte(i)));
break;
case asTYPEID_INT16:
case asTYPEID_UINT16:
AS_CHECK(scriptContext->SetArgWord(i, genericFun->GetArgWord(i)));
break;
case asTYPEID_INT32:
case asTYPEID_UINT32:
AS_CHECK(scriptContext->SetArgDWord(i, genericFun->GetArgDWord(i)));
break;
case asTYPEID_INT64:
case asTYPEID_UINT64:
AS_CHECK(scriptContext->SetArgQWord(i, genericFun->GetArgQWord(i)));
break;
case asTYPEID_FLOAT:
AS_CHECK(scriptContext->SetArgFloat(i, genericFun->GetArgFloat(i)));
break;
case asTYPEID_DOUBLE:
AS_CHECK(scriptContext->SetArgDouble(i, genericFun->GetArgDouble(i)));
break;
default:
AS_CHECK(scriptContext->SetArgObject(i, genericFun->GetArgObject(i)));
break;
}
}
}
AS_CHECK(scriptContext->Execute());
int retTypeId = genericFun->GetReturnTypeId();
if (retTypeId == asTYPEID_VOID) {
} else if (retTypeId & asTYPEID_OBJHANDLE) {
void* obj = scriptContext->GetReturnObject();
genericFun->SetReturnObject(obj);
} else if (retTypeId & asTYPEID_MASK_OBJECT) {
void* obj = scriptContext->GetReturnObject();
genericFun->SetReturnObject(obj);
} else {
switch (retTypeId) {
case asTYPEID_BOOL:
case asTYPEID_INT8:
case asTYPEID_UINT8:
genericFun->SetReturnByte(scriptContext->GetReturnByte());
break;
case asTYPEID_INT16:
case asTYPEID_UINT16:
genericFun->SetReturnWord(scriptContext->GetReturnWord());
break;
case asTYPEID_INT32:
case asTYPEID_UINT32:
genericFun->SetReturnDWord(scriptContext->GetReturnDWord());
break;
case asTYPEID_INT64:
case asTYPEID_UINT64:
genericFun->SetReturnQWord(scriptContext->GetReturnQWord());
break;
case asTYPEID_FLOAT:
genericFun->SetReturnFloat(scriptContext->GetReturnFloat());
break;
case asTYPEID_DOUBLE:
genericFun->SetReturnDouble(scriptContext->GetReturnDouble());
break;
default:
// value types returned by value
genericFun->SetReturnObject(scriptContext->GetReturnObject());
break;
}
}
AS_CHECK(scriptContext->PopState());
}
void Service::updateTypes(asIScriptModule* module) {
type = module->GetTypeInfoByName(typeName.c_str());
updateFunction = type->GetMethodByDecl("void update()");
initFunction = type->GetMethodByDecl("void init()");
shutdownFunction = type->GetMethodByDecl("void shutdown()");
for (Scope<ServiceExposedFunctionData>& exposedFunction : exposedFunctions) {
exposedFunction->exposedFunction = type->GetMethodByName(exposedFunction->exposedFunctionName.c_str());
exposedFunction->exposedObject = object;
}
}
void Service::update() {
if (!updateFunction)
return;
@ -70,6 +286,8 @@ namespace Deer {
Service::Service(asITypeInfo* _type)
: type(_type) {
typeName = _type->GetName();
updateFunction = type->GetMethodByDecl("void update()");
initFunction = type->GetMethodByDecl("void init()");
shutdownFunction = type->GetMethodByDecl("void shutdown()");

View File

@ -1,8 +1,21 @@
Entity entity = Resource::getMainEnvironment().getRootEntity();
class ActiveEntity : Service {
Entity entity;
[Expose]
Entity getActiveEntity() {
return entity;
}
[Expose]
void setActiveEntity(Entity ent) {
entity = ent;
}
void init() {
entity = Resource::getMainEnvironment().getRootEntity();
}
[Expose]
void wtf() {
Engine::print("Exposed");
}
}

View File

@ -57,4 +57,8 @@ class MeshComponentRender {
entity.removeMeshComponent();
}
}
void init() {
ActiveEntity::wtf();
}
}

View File

@ -1,13 +1,10 @@
import Entity getActiveEntity() from "ActiveEntity";
import void setActiveEntity(Entity) from "ActiveEntity";
class PropertiesPanel : Panel {
float slider = 0;
vec3 slid;
vec3 slid2;
void render() {
Entity entity = getActiveEntity();
Entity entity = ActiveEntity::getActiveEntity();
// NAME
// Id:0 [+ add component]
@ -60,7 +57,7 @@ class PropertiesPanel : Panel {
}
void renameEntityMenu() {
Entity entity = getActiveEntity();
Entity entity = ActiveEntity::getActiveEntity();
if (!entity.isRoot) {
if (UI::menuItem("Rename")) {

View File

@ -1,19 +1,10 @@
RenderService@ mainRenderService;
FrameBuffer renderMeshPreview(GPUMesh mesh) {
return mainRenderService.renderMeshPreview(mesh);
}
FrameBuffer renderMeshPreview(GPUMesh mesh, float fase) {
return mainRenderService.renderMeshPreview(mesh, fase);
}
void setSceneCamera(SceneCamera sc) {
}
class RenderService : Service {
Environment env;
SceneCamera sceneCamera;
MeshComponent meshC;
Entity child;
void init() {
@mainRenderService = this;
env = Resource::createLoadEnvironment("PreviewerEnv");
child = env.getRootEntity().createChild("Render");
@ -27,30 +18,27 @@ class RenderService : Service {
}
[Expose]
FrameBuffer renderMeshPreview(GPUMesh mesh) {
FrameBuffer buffer = Resource::createLoadRGBA8FrameBuffer(mesh.path, 128, 128, 4);
buffer.clearRGBA(0, 0, 0, 0);
meshC.meshResource = mesh;
child.transform.rotation = vec3(0, 0, 0);
mainRenderService.env.render(buffer, mainRenderService.sceneCamera);
env.render(buffer, sceneCamera);
return buffer;
}
FrameBuffer renderMeshPreview(GPUMesh mesh, float fase) {
[Expose]
FrameBuffer renderMeshPreview_fase(GPUMesh mesh, float fase) {
FrameBuffer buffer = Resource::createLoadRGBA8FrameBuffer(mesh.path, 128, 128, 4);
buffer.clearRGBA(0, 0, 0, 0);
meshC.meshResource = mesh;
child.transform.rotation = vec3(0, (1-(1/(1+fase * fase)))*45, 0);
mainRenderService.env.render(buffer, mainRenderService.sceneCamera);
env.render(buffer, sceneCamera);
return buffer;
}
Environment env;
SceneCamera sceneCamera;
MeshComponent meshC;
Entity child;
}

View File

@ -1,5 +1,3 @@
import FrameBuffer renderMeshPreview(GPUMesh mesh) from "Previewer";
import FrameBuffer renderMeshPreview(GPUMesh mesh, float fase) from "Previewer";
string selectedResource = "";
class ResourceExplorer : Panel {
@ -62,7 +60,7 @@ class ResourceExplorer : Panel {
//}
GPUMesh mesh = Resource::loadGPUMesh(filename);
frameBuffer = renderMeshPreview(mesh, fase);
frameBuffer = Previewer::renderMeshPreview_fase(mesh, fase);
meshFrameBuffer[filename] = frameBuffer;
alreadyRendered = true;

View File

@ -0,0 +1,8 @@
class Test : Service {
void init() {
Engine::print("Initing");
Entity entity = ActiveEntity::getActiveEntity();
Engine::print(entity.name);
Engine::print("Ending");
}
}

View File

@ -0,0 +1,5 @@
{
"patch": 1,
"name": "Test",
"requires": ["ActiveEntity"]
}

View File

@ -1,6 +1,3 @@
import Entity getActiveEntity() from "ActiveEntity";
import void setActiveEntity(Entity) from "ActiveEntity";
class EntityTreeRender {
EntityTreeRender(Entity _entity) {
entity = _entity;
@ -8,7 +5,7 @@ class EntityTreeRender {
Entity entity;
bool isActiveEntity() {
return entity == getActiveEntity();
return entity == ActiveEntity::getActiveEntity();
}
void renderEntity() {
@ -47,7 +44,7 @@ class EntityTreeRender {
UI::contextItemPopup("POP_ENTITY_" + entity.id, Callback(this.renderContextMenu));
if (UI::isItemClicked(0)) {
setActiveEntity(entity);
ActiveEntity::setActiveEntity(entity);
}
}

View File

@ -1,5 +1,3 @@
import void setSceneCamera (SceneCamera sc) from "Previewer";
class ViewportPanel : Panel {
FrameBuffer frameBuffer;
SceneCamera sceneCamera;
@ -68,7 +66,6 @@ class ViewportPanel : Panel {
vertically--;
sceneCamera.transform.position = sceneCamera.transform.position + vec3(0, vertically * vel, 0);
setSceneCamera(sceneCamera);
}
void init() {