Reflection rework (#1357)

new reflection system - faster to compiler, saner errors
This commit is contained in:
Mikulas Florek 2021-03-04 22:06:18 +01:00 committed by GitHub
parent b2ea3536cb
commit 4bf33479b1
40 changed files with 1005 additions and 1189 deletions

View File

@ -1,7 +1,6 @@
#pragma once
#include "engine/hash_map.h"
#include "engine/math.h"
#include "engine/resource.h"
#include "engine/string.h"

View File

@ -950,24 +950,21 @@ UniquePtr<AnimationScene> AnimationScene::create(Engine& engine, IPlugin& plugin
}
void AnimationScene::reflect(Engine& engine) {
LUMIX_SCENE(AnimationSceneImpl, "animation",
LUMIX_CMP(PropertyAnimator, "property_animator", "Animation / Property animator",
LUMIX_PROP(PropertyAnimation, "Animation", ResourceAttribute(PropertyAnimation::TYPE)),
property("Enabled", &AnimationScene::isPropertyAnimatorEnabled, &AnimationScene::enablePropertyAnimator)
),
LUMIX_CMP(Animator, "animator", "Animation / Animator",
function((void (AnimationScene::*)(EntityRef, u32, u32))&AnimationScene::setAnimatorInput, "AnimationScene::setAnimatorInput", "setU32Input"),
function((void (AnimationScene::*)(EntityRef, u32, float))&AnimationScene::setAnimatorInput, "AnimationScene::setAnimatorInput", "setFloatInput"),
function((void (AnimationScene::*)(EntityRef, u32, bool))&AnimationScene::setAnimatorInput, "AnimationScene::setAnimatorInput", "setBoolInput"),
LUMIX_FUNC_EX(AnimationScene::getAnimatorInputIndex, "getInputIndex"),
LUMIX_FUNC_EX(AnimationScene::setAnimatorIK, "setIK"),
LUMIX_PROP(AnimatorSource, "Source", ResourceAttribute(anim::Controller::TYPE)),
LUMIX_PROP(AnimatorDefaultSet, "Default set")
),
LUMIX_CMP(Animable, "animable", "Animation / Animable",
LUMIX_PROP(Animation, "Animation", ResourceAttribute(Animation::TYPE))
)
);
LUMIX_SCENE(AnimationSceneImpl, "animation")
.LUMIX_CMP(PropertyAnimator, "property_animator", "Animation / Property animator")
.LUMIX_PROP(PropertyAnimation, "Animation").resourceAttribute(PropertyAnimation::TYPE)
.prop<&AnimationScene::isPropertyAnimatorEnabled, &AnimationScene::enablePropertyAnimator>("Enabled")
.LUMIX_CMP(Animator, "animator", "Animation / Animator")
.function<(void (AnimationScene::*)(EntityRef, u32, u32))&AnimationScene::setAnimatorInput>("AnimationScene::setAnimatorInput", "setU32Input")
.function<(void (AnimationScene::*)(EntityRef, u32, float))&AnimationScene::setAnimatorInput>("AnimationScene::setAnimatorInput", "setFloatInput")
.function<(void (AnimationScene::*)(EntityRef, u32, bool))&AnimationScene::setAnimatorInput>("AnimationScene::setAnimatorInput", "setBoolInput")
.LUMIX_FUNC_EX(getAnimatorInputIndex, "getInputIndex")
.LUMIX_FUNC_EX(setAnimatorIK, "setIK")
.LUMIX_PROP(AnimatorSource, "Source").resourceAttribute(anim::Controller::TYPE)
.LUMIX_PROP(AnimatorDefaultSet, "Default set")
.LUMIX_CMP(Animable, "animable", "Animation / Animable")
.LUMIX_PROP(Animation, "Animation").resourceAttribute(Animation::TYPE)
;
}
} // namespace Lumix

View File

@ -4,7 +4,6 @@
#include "animation/property_animation.h"
#include "animation/controller.h"
#include "engine/engine.h"
#include "engine/reflection.h"
#include "engine/resource_manager.h"
#include "engine/universe.h"

View File

@ -9,7 +9,6 @@
#include "engine/crc32.h"
#include "engine/engine.h"
#include "engine/log.h"
#include "engine/reflection.h"
#include "engine/resource_manager.h"
#include "engine/universe.h"
#include "renderer/model.h"

View File

@ -490,27 +490,24 @@ UniquePtr<AudioScene> AudioScene::createInstance(AudioSystem& system,
}
void AudioScene::reflect(Engine& engine) {
LUMIX_SCENE(AudioSceneImpl, "audio",
LUMIX_FUNC(AudioScene::setMasterVolume),
LUMIX_FUNC(AudioScene::play),
LUMIX_FUNC(AudioScene::setVolume),
LUMIX_FUNC(AudioScene::setEcho),
LUMIX_CMP(AmbientSound, "ambient_sound", "Audio / Ambient sound",
LUMIX_FUNC_EX(AudioScene::pauseAmbientSound, "pause"),
LUMIX_FUNC_EX(AudioScene::resumeAmbientSound, "resume"),
property("3D", &AudioScene::isAmbientSound3D, &AudioScene::setAmbientSound3D),
LUMIX_PROP(AmbientSoundClip, "Sound", ResourceAttribute(Clip::TYPE))
),
LUMIX_CMP(Listener, "audio_listener", "Audio / Listener", icon(ICON_FA_HEADPHONES)),
LUMIX_CMP(EchoZone, "echo_zone", "Audio / Echo zone",
var_property("Radius", &AudioScene::getEchoZone, &EchoZone::radius, MinAttribute(0)),
var_property("Delay (ms)", &AudioScene::getEchoZone, &EchoZone::delay, MinAttribute(0))
),
LUMIX_CMP(ChorusZone, "chorus_zone", "Audio / Chorus zone",
var_property("Radius", &AudioScene::getChorusZone, &ChorusZone::radius, MinAttribute(0)),
var_property("Delay (ms)", &AudioScene::getChorusZone, &ChorusZone::delay, MinAttribute(0))
)
);
LUMIX_SCENE(AudioSceneImpl, "audio")
.LUMIX_FUNC(AudioScene::setMasterVolume)
.LUMIX_FUNC(AudioScene::play)
.LUMIX_FUNC(AudioScene::setVolume)
.LUMIX_FUNC(AudioScene::setEcho)
.LUMIX_CMP(AmbientSound, "ambient_sound", "Audio / Ambient sound")
.LUMIX_FUNC_EX(AudioScene::pauseAmbientSound, "pause")
.LUMIX_FUNC_EX(AudioScene::resumeAmbientSound, "resume")
.prop<&AudioScene::isAmbientSound3D, &AudioScene::setAmbientSound3D>("3D")
.LUMIX_PROP(AmbientSoundClip, "Sound").resourceAttribute(Clip::TYPE)
.LUMIX_CMP(Listener, "audio_listener", "Audio / Listener").icon(ICON_FA_HEADPHONES)
.LUMIX_CMP(EchoZone, "echo_zone", "Audio / Echo zone")
.var_prop<&AudioScene::getEchoZone, &EchoZone::radius>("Radius").minAttribute(0)
.var_prop<&AudioScene::getEchoZone, &EchoZone::delay>("Delay (ms)").minAttribute(0)
.LUMIX_CMP(ChorusZone, "chorus_zone", "Audio / Chorus zone")
.var_prop<&AudioScene::getChorusZone, &ChorusZone::radius>("Radius").minAttribute(0)
.var_prop<&AudioScene::getChorusZone, &ChorusZone::delay>("Delay (ms)").minAttribute(0)
;
}

View File

@ -12,7 +12,6 @@
#include "engine/crc32.h"
#include "engine/engine.h"
#include "engine/lua_wrapper.h"
#include "engine/reflection.h"
#include "engine/universe.h"

View File

@ -335,25 +335,25 @@ public:
void visit(const reflection::Property<bool>& prop) override { clone(prop); }
void visit(const reflection::Property<const char*>& prop) override { clone(prop); }
void visit(const reflection::IArrayProperty& prop) override {
const i32 c = prop.getCount(src);
void visit(const reflection::ArrayProperty& prop) override {
const u32 c = prop.getCount(src);
while (prop.getCount(dst) < c) { prop.addItem(dst, prop.getCount(dst) - 1); }
while (prop.getCount(dst) > c) { prop.removeItem(dst, prop.getCount(dst) - 1); }
ASSERT(index == -1);
for (int i = 0; i < c; ++i) {
for (u32 i = 0; i < c; ++i) {
index = i;
prop.visit(*this);
}
index = -1;
}
void visit(const reflection::IDynamicProperties& prop) override {
void visit(const reflection::DynamicProperties& prop) override {
for (u32 i = 0, c = prop.getCount(src, index); i < c; ++i) {
const char* name = prop.getName(src, index, i);
reflection::IDynamicProperties::Type type = prop.getType(src, index, i);
reflection::IDynamicProperties::Value val = prop.getValue(src, index, i);
if (type == reflection::IDynamicProperties::ENTITY) {
reflection::DynamicProperties::Type type = prop.getType(src, index, i);
reflection::DynamicProperties::Value val = prop.getValue(src, index, i);
if (type == reflection::DynamicProperties::ENTITY) {
auto iter = map->find(val.e);
if (iter.isValid()) {
val.e = iter.value();
@ -365,12 +365,15 @@ public:
prop.set(dst, index, name, type, val);
}
}
void visit(const reflection::IBlobProperty& prop) override {
void visit(const reflection::BlobProperty& prop) override {
OutputMemoryStream tmp(*allocator);
prop.getValue(src, index, tmp);
InputMemoryStream blob(tmp);
prop.setValue(dst, index, blob);
}
const HashMap<EntityPtr, EntityPtr>* map;
IAllocator* allocator;

View File

@ -78,7 +78,7 @@ struct GridUIVisitor final : reflection::IPropertyVisitor
static Attributes getAttributes(const reflection::Property<T>& prop)
{
Attributes attrs;
for (const reflection::IAttribute* attr : prop.getAttributes()) {
for (const reflection::IAttribute* attr : prop.attributes) {
switch (attr->getType()) {
case reflection::IAttribute::RADIANS:
attrs.is_radians = true;
@ -108,90 +108,92 @@ struct GridUIVisitor final : reflection::IPropertyVisitor
}
template <typename T>
void dynamicProperty(const ComponentUID& cmp, const reflection::IDynamicProperties& prop, u32 prop_index) {
struct : reflection::Property<T> {
Span<const reflection::IAttribute* const> getAttributes() const override { return {}; }
void dynamicProperty(const ComponentUID& cmp, const reflection::DynamicProperties& prop, u32 prop_index) {
struct Prop : reflection::Property<T> {
Prop(IAllocator& allocator) : reflection::Property<T>(allocator) {}
T get(ComponentUID cmp, int array_index) const override {
T get(ComponentUID cmp, u32 array_index) const override {
return reflection::get<T>(prop->getValue(cmp, array_index, index));
}
void set(ComponentUID cmp, int array_index, T value) const override {
reflection::IDynamicProperties::Value v;
void set(ComponentUID cmp, u32 array_index, T value) const override {
reflection::DynamicProperties::Value v;
reflection::set<T>(v, value);
prop->set(cmp, array_index, index, v);
}
const reflection::IDynamicProperties* prop;
const reflection::DynamicProperties* prop;
ComponentUID cmp;
int index;
} p;
} p(m_app.getAllocator());
p.name = prop.getName(cmp, m_index, prop_index);
p.prop = &prop;
p.index = prop_index;
visit(p);
}
void visit(const reflection::IDynamicProperties& prop) override {
void visit(const reflection::DynamicProperties& prop) override {
ComponentUID cmp = getComponent();;
for (u32 i = 0, c = prop.getCount(cmp, m_index); i < c; ++i) {
const reflection::IDynamicProperties::Type type = prop.getType(cmp, m_index, i);
const reflection::DynamicProperties::Type type = prop.getType(cmp, m_index, i);
switch(type) {
case reflection::IDynamicProperties::FLOAT: dynamicProperty<float>(cmp, prop, i); break;
case reflection::IDynamicProperties::BOOLEAN: dynamicProperty<bool>(cmp, prop, i); break;
case reflection::IDynamicProperties::ENTITY: dynamicProperty<EntityPtr>(cmp, prop, i); break;
case reflection::IDynamicProperties::I32: dynamicProperty<i32>(cmp, prop, i); break;
case reflection::IDynamicProperties::STRING: dynamicProperty<const char*>(cmp, prop, i); break;
case reflection::IDynamicProperties::COLOR: {
struct : reflection::Property<Vec3> {
Span<const reflection::IAttribute* const> getAttributes() const override {
return Span((const reflection::IAttribute*const*)attrs, 1);
}
Vec3 get(ComponentUID cmp, int array_index) const override {
case reflection::DynamicProperties::FLOAT: dynamicProperty<float>(cmp, prop, i); break;
case reflection::DynamicProperties::BOOLEAN: dynamicProperty<bool>(cmp, prop, i); break;
case reflection::DynamicProperties::ENTITY: dynamicProperty<EntityPtr>(cmp, prop, i); break;
case reflection::DynamicProperties::I32: dynamicProperty<i32>(cmp, prop, i); break;
case reflection::DynamicProperties::STRING: dynamicProperty<const char*>(cmp, prop, i); break;
case reflection::DynamicProperties::COLOR: {
struct Prop : reflection::Property<Vec3> {
Prop(IAllocator& allocator) : Property<Vec3>(allocator) {}
Vec3 get(ComponentUID cmp, u32 array_index) const override {
return reflection::get<Vec3>(prop->getValue(cmp, array_index, index));
}
void set(ComponentUID cmp, int array_index, Vec3 value) const override {
reflection::IDynamicProperties::Value v;
void set(ComponentUID cmp, u32 array_index, Vec3 value) const override {
reflection::DynamicProperties::Value v;
reflection::set(v, value);
prop->set(cmp, array_index, index, v);
}
const reflection::IDynamicProperties* prop;
const reflection::DynamicProperties* prop;
ComponentUID cmp;
int index;
reflection::ColorAttribute attr;
reflection::IAttribute* attrs[1] = { &attr };
} p;
} p(m_app.getAllocator());
p.name = prop.getName(cmp, m_index, i);
p.prop = &prop;
p.index = i;
p.attributes.push(&p.attr);
visit(p);
break;
}
case reflection::IDynamicProperties::RESOURCE: {
struct : reflection::Property<Path> {
Span<const reflection::IAttribute* const> getAttributes() const override {
return Span((const reflection::IAttribute*const*)attrs, 1);
}
Path get(ComponentUID cmp, int array_index) const override {
case reflection::DynamicProperties::RESOURCE: {
struct Prop : reflection::Property<Path> {
Prop(IAllocator& allocator) : Property<Path>(allocator) {}
Path get(ComponentUID cmp, u32 array_index) const override {
return Path(reflection::get<const char*>(prop->getValue(cmp, array_index, index)));
}
void set(ComponentUID cmp, int array_index, Path value) const override {
reflection::IDynamicProperties::Value v;
void set(ComponentUID cmp, u32 array_index, Path value) const override {
reflection::DynamicProperties::Value v;
reflection::set(v, value.c_str());
prop->set(cmp, array_index, index, v);
}
const reflection::IDynamicProperties* prop;
const reflection::DynamicProperties* prop;
ComponentUID cmp;
int index;
reflection::ResourceAttribute attr;
reflection::IAttribute* attrs[1] = { &attr };
} p;
} p(m_app.getAllocator());
p.attr = prop.getResourceAttribute(cmp, m_index, i);
p.name = prop.getName(cmp, m_index, i);
p.prop = &prop;
p.index = i;
p.attributes.push(&p.attr);
visit(p);
break;
}
@ -200,7 +202,6 @@ struct GridUIVisitor final : reflection::IPropertyVisitor
}
}
void visit(const reflection::Property<float>& prop) override
{
Attributes attrs = getAttributes(prop);
@ -556,11 +557,9 @@ struct GridUIVisitor final : reflection::IPropertyVisitor
ImGui::PopID();
}
void visit(const reflection::BlobProperty& prop) override {}
void visit(const reflection::IBlobProperty& prop) override {}
void visit(const reflection::IArrayProperty& prop) override
void visit(const reflection::ArrayProperty& prop) override
{
ImGui::Unindent();
bool is_open = ImGui::TreeNodeEx(prop.name, ImGuiTreeNodeFlags_AllowItemOverlap);
@ -611,7 +610,7 @@ struct GridUIVisitor final : reflection::IPropertyVisitor
{
GridUIVisitor v(m_app, i, m_entities, m_cmp_type, m_editor);
v.m_array = prop.name;
prop.visit(v);
prop.visitChildren(v);
ImGui::TreePop();
}

View File

@ -2581,7 +2581,7 @@ struct StudioAppImpl final : StudioApp
struct : reflection::IEmptyPropertyVisitor {
void visit(const reflection::Property<Path>& prop) override {
for (const reflection::IAttribute* attr : prop.getAttributes()) {
for (const reflection::IAttribute* attr : prop.attributes) {
if (attr->getType() == reflection::IAttribute::RESOURCE) {
is_res = true;
reflection::ResourceAttribute* a = (reflection::ResourceAttribute*)attr;
@ -2792,8 +2792,8 @@ struct StudioAppImpl final : StudioApp
}
void visit(const reflection::Property<EntityPtr>& prop) override { notSupported(prop); }
void visit(const reflection::IArrayProperty& prop) override { notSupported(prop); }
void visit(const reflection::IBlobProperty& prop) override { notSupported(prop); }
void visit(const reflection::ArrayProperty& prop) override { notSupported(prop); }
void visit(const reflection::BlobProperty& prop) override { notSupported(prop); }
template <typename T>
void notSupported(const T& prop)

View File

@ -3,7 +3,6 @@
#include "utils.h"
#include "engine/math.h"
#include "engine/path.h"
#include "engine/reflection.h"
#include "editor/render_interface.h"
#include "editor/studio_app.h"
#include "editor/world_editor.h"

View File

@ -341,6 +341,51 @@ void addSphere(UniverseView& view, const DVec3& center, float radius, Color colo
}
}
template <typename T> void writeToStream(OutputMemoryStream& stream, T value) { stream.write(value); }
template <typename T> T readFromStream(InputMemoryStream& stream) { return stream.read<T>(); }
template <> LUMIX_ENGINE_API Path readFromStream<Path>(InputMemoryStream& stream);
template <> LUMIX_ENGINE_API void writeToStream<Path>(OutputMemoryStream& stream, Path);
template <> LUMIX_ENGINE_API void writeToStream<const Path&>(OutputMemoryStream& stream, const Path& path);
template <> LUMIX_ENGINE_API const char* readFromStream<const char*>(InputMemoryStream& stream);
template <> LUMIX_ENGINE_API void writeToStream<const char*>(OutputMemoryStream& stream, const char* path);
template <> Path readFromStream<Path>(InputMemoryStream& stream)
{
const char* c_str = (const char*)stream.getData() + stream.getPosition();
Path path(c_str);
stream.skip(stringLength(c_str) + 1);
return path;
}
template <> void writeToStream<const Path&>(OutputMemoryStream& stream, const Path& path)
{
const char* str = path.c_str();
stream.write(str, stringLength(str) + 1);
}
template <> void writeToStream<Path>(OutputMemoryStream& stream, Path path)
{
const char* str = path.c_str();
stream.write(str, stringLength(str) + 1);
}
template <> const char* readFromStream<const char*>(InputMemoryStream& stream)
{
const char* c_str = (const char*)stream.getData() + stream.getPosition();
stream.skip(stringLength(c_str) + 1);
return c_str;
}
template <> void writeToStream<const char*>(OutputMemoryStream& stream, const char* value)
{
stream.write(value, stringLength(value) + 1);
}
struct PropertyDeserializeVisitor : reflection::IPropertyVisitor {
PropertyDeserializeVisitor(Ref<InputMemoryStream> deserializer
, ComponentUID cmp
@ -354,7 +399,7 @@ struct PropertyDeserializeVisitor : reflection::IPropertyVisitor {
template <typename T>
void set(const reflection::Property<T>& prop) {
prop.set(cmp, idx, reflection::readFromStream<T>(deserializer));
prop.set(cmp, idx, readFromStream<T>(deserializer));
}
void visit(const reflection::Property<float>& prop) override { set(prop); }
@ -365,28 +410,28 @@ struct PropertyDeserializeVisitor : reflection::IPropertyVisitor {
void visit(const reflection::Property<IVec3>& prop) override { set(prop); }
void visit(const reflection::Property<Vec4>& prop) override { set(prop); }
void visit(const reflection::Property<bool>& prop) override { set(prop); }
void visit(const reflection::IBlobProperty& prop) override { prop.setValue(cmp, idx, deserializer); }
void visit(const reflection::Property<const char*>& prop) override { set(prop); }
void visit(const reflection::Property<Path>& prop) override { set(prop); }
void visit(const reflection::BlobProperty& prop) override { prop.setValue(cmp, idx, deserializer); }
void visit(const reflection::IDynamicProperties& prop) override {
void visit(const reflection::DynamicProperties& prop) override {
u32 c;
deserializer.read(c);
for (u32 i = 0; i < c; ++i) {
const char* name = deserializer.readString();
reflection::IDynamicProperties::Type type;
reflection::DynamicProperties::Type type;
deserializer.read(type);
switch(type) {
case reflection::IDynamicProperties::RESOURCE:
case reflection::IDynamicProperties::STRING: {
case reflection::DynamicProperties::RESOURCE:
case reflection::DynamicProperties::STRING: {
const char* tmp = deserializer.readString();
reflection::IDynamicProperties::Value v;
reflection::DynamicProperties::Value v;
v.s = tmp;
prop.set(cmp, idx, name, type, v);
break;
}
default: {
reflection::IDynamicProperties::Value v;
reflection::DynamicProperties::Value v;
deserializer.read(v);
prop.set(cmp, idx, name, type, v);
break;
@ -394,7 +439,7 @@ struct PropertyDeserializeVisitor : reflection::IPropertyVisitor {
}
}
}
void visit(const reflection::Property<EntityPtr>& prop) override {
EntityPtr value;
deserializer.read(Ref(value));
@ -404,8 +449,8 @@ struct PropertyDeserializeVisitor : reflection::IPropertyVisitor {
prop.set(cmp, idx, value);
}
void visit(const reflection::IArrayProperty& prop) override {
int count;
void visit(const reflection::ArrayProperty& prop) override {
u32 count;
deserializer.read(Ref(count));
const int idx_backup = idx;
while (prop.getCount(cmp) > count) {
@ -414,9 +459,9 @@ struct PropertyDeserializeVisitor : reflection::IPropertyVisitor {
while (prop.getCount(cmp) < count) {
prop.addItem(cmp, -1);
}
for (int i = 0; i < count; ++i) {
for (u32 i = 0; i < count; ++i) {
idx = i;
prop.visit(*this);
prop.visitChildren(*this);
}
idx = idx_backup;
}
@ -436,7 +481,7 @@ struct PropertySerializeVisitor : reflection::IPropertyVisitor {
template <typename T>
void get(const reflection::Property<T>& prop) {
reflection::writeToStream(serializer, prop.get(cmp, idx));
writeToStream(serializer, prop.get(cmp, idx));
}
void visit(const reflection::Property<float>& prop) override { get(prop); }
@ -448,22 +493,22 @@ struct PropertySerializeVisitor : reflection::IPropertyVisitor {
void visit(const reflection::Property<IVec3>& prop) override { get(prop); }
void visit(const reflection::Property<Vec4>& prop) override { get(prop); }
void visit(const reflection::Property<bool>& prop) override { get(prop); }
void visit(const reflection::IBlobProperty& prop) override { prop.getValue(cmp, idx, serializer); }
void visit(const reflection::BlobProperty& prop) override { prop.getValue(cmp, idx, serializer); }
void visit(const reflection::Property<Path>& prop) override { get(prop); }
void visit(const reflection::Property<const char*>& prop) override { get(prop); }
void visit(const reflection::IDynamicProperties& prop) override {
void visit(const reflection::DynamicProperties& prop) override {
const u32 c = prop.getCount(cmp, idx);
serializer.write(c);
for (u32 i = 0; i < c; ++i) {
const char* name = prop.getName(cmp, idx, i);
serializer.writeString(name);
const reflection::IDynamicProperties::Type type = prop.getType(cmp, idx, i);
const reflection::DynamicProperties::Type type = prop.getType(cmp, idx, i);
serializer.write(type);
const reflection::IDynamicProperties::Value v = prop.getValue(cmp, idx, i);
const reflection::DynamicProperties::Value v = prop.getValue(cmp, idx, i);
switch(type) {
case reflection::IDynamicProperties::RESOURCE:
case reflection::IDynamicProperties::STRING:
case reflection::DynamicProperties::RESOURCE:
case reflection::DynamicProperties::STRING:
serializer.writeString(v.s);
break;
default:
@ -473,20 +518,20 @@ struct PropertySerializeVisitor : reflection::IPropertyVisitor {
}
}
void visit(const reflection::IArrayProperty& prop) override {
void visit(const reflection::ArrayProperty& prop) override {
const int count = prop.getCount(cmp);
serializer.write(count);
const int idx_backup = idx;
for (int i = 0; i < count; ++i) {
idx = i;
prop.visit(*this);
prop.visitChildren(*this);
}
idx = idx_backup;
}
OutputMemoryStream& serializer;
ComponentUID cmp;
int idx;
int idx = -1;
};
@ -917,12 +962,12 @@ private:
struct GatherResourcesVisitor final : reflection::IEmptyPropertyVisitor
{
void visit(const reflection::IArrayProperty& prop) override
void visit(const reflection::ArrayProperty& prop) override
{
int count = prop.getCount(cmp);
for (int i = 0; i < count; ++i) {
index = i;
prop.visit(*this);
prop.visitChildren(*this);
}
index = -1;
}
@ -966,7 +1011,7 @@ public:
bool execute() override
{
struct : reflection::IEmptyPropertyVisitor {
void visit(const reflection::IArrayProperty& prop) override {
void visit(const reflection::ArrayProperty& prop) override {
if (!equalStrings(prop.name, propname)) return;
prop.removeItem(cmp, index);
}
@ -1022,20 +1067,9 @@ public:
bool execute() override
{
struct : reflection::IEmptyPropertyVisitor {
void visit(const reflection::IArrayProperty& prop) override {
if (!equalStrings(prop.name, prop_name)) return;
index = prop.getCount(cmp);
prop.addItem(cmp, index);
}
ComponentUID cmp;
int index;
const char* prop_name;
} v;
v.cmp = m_component;
v.prop_name = m_property;
reflection::getComponent(m_component.type)->visit(v);
m_index = v.index;
reflection::ArrayProperty* prop = (reflection::ArrayProperty*)reflection::getProperty(m_component.type, m_property);
m_index = prop->getCount(m_component);
prop->addItem(m_component, m_index);
return true;
}
@ -1043,7 +1077,7 @@ public:
void undo() override
{
struct : reflection::IEmptyPropertyVisitor {
void visit(const reflection::IArrayProperty& prop) override {
void visit(const reflection::ArrayProperty& prop) override {
if (!equalStrings(prop.name, prop_name)) return;
prop.removeItem(cmp, index);
}
@ -1133,15 +1167,15 @@ public:
}
template <typename T2> static void set(Ref<reflection::IDynamicProperties::Value> v, T2) { ASSERT(false); }
static void set(Ref<reflection::IDynamicProperties::Value> v, i32 val) { reflection::set(v.value, val); }
static void set(Ref<reflection::IDynamicProperties::Value> v, float val) { reflection::set(v.value, val); }
static void set(Ref<reflection::IDynamicProperties::Value> v, const Path& val) { reflection::set(v.value, val.c_str()); }
static void set(Ref<reflection::IDynamicProperties::Value> v, const char* val) { reflection::set(v.value, val); }
static void set(Ref<reflection::IDynamicProperties::Value> v, EntityPtr val) { reflection::set(v.value, val); }
static void set(Ref<reflection::IDynamicProperties::Value> v, bool val) { reflection::set(v.value, val); }
static void set(Ref<reflection::IDynamicProperties::Value> v, Vec3 val) { reflection::set(v.value, val); }
static void set(Ref<reflection::IDynamicProperties::Value> v, const String& val) { reflection::set(v.value, val.c_str()); }
template <typename T2> static void set(Ref<reflection::DynamicProperties::Value> v, T2) { ASSERT(false); }
static void set(Ref<reflection::DynamicProperties::Value> v, i32 val) { reflection::set(v.value, val); }
static void set(Ref<reflection::DynamicProperties::Value> v, float val) { reflection::set(v.value, val); }
static void set(Ref<reflection::DynamicProperties::Value> v, const Path& val) { reflection::set(v.value, val.c_str()); }
static void set(Ref<reflection::DynamicProperties::Value> v, const char* val) { reflection::set(v.value, val); }
static void set(Ref<reflection::DynamicProperties::Value> v, EntityPtr val) { reflection::set(v.value, val); }
static void set(Ref<reflection::DynamicProperties::Value> v, bool val) { reflection::set(v.value, val); }
static void set(Ref<reflection::DynamicProperties::Value> v, Vec3 val) { reflection::set(v.value, val); }
static void set(Ref<reflection::DynamicProperties::Value> v, const String& val) { reflection::set(v.value, val.c_str()); }
bool execute() override
@ -1157,16 +1191,17 @@ public:
}
}
void visit(const reflection::IArrayProperty& prop) override {
void visit(const reflection::ArrayProperty& prop) override {
if (!equalStrings(array, prop.name)) return;
const char* tmp = array;
array = "";
prop.visit(*this);
prop.visitChildren(*this);
array = tmp;
}
void visit(const reflection::IDynamicProperties& prop) override {
// TODO refl
/*
void visit(const reflection::DynamicProperties& prop) override {
for (EntityPtr entity : cmd->m_entities) {
const ComponentUID cmp = cmd->m_editor.getUniverse()->getComponent((EntityRef)entity, cmd->m_component_type);
const u32 c = prop.getCount(cmp, cmd->m_index);
@ -1174,12 +1209,12 @@ public:
const char* name = prop.getName(cmp, cmd->m_index, i);
if (!equalStrings(prop_name, name)) continue;
found = true;
reflection::IDynamicProperties::Value v;
reflection::DynamicProperties::Value v;
set(Ref(v), cmd->m_new_value);
prop.set(cmp, cmd->m_index, i, v);
}
}
}
}*/
SetPropertyCommand<T>* cmd;
const char* prop_name;
const char* array;

View File

@ -13,7 +13,6 @@
#include "engine/path.h"
#include "engine/prefab.h"
#include "engine/profiler.h"
#include "engine/reflection.h"
#include "engine/resource_manager.h"
#include "engine/stream.h"
#include "engine/universe.h"

View File

@ -222,6 +222,8 @@ inline EntityPtr::operator EntityRef() const
return {index};
}
namespace reflection { LUMIX_ENGINE_API ComponentType getComponentType(const char* id); }
#ifdef _MSC_VER
#pragma warning(disable : 4251)
// this is disabled because VS19 16.5.0 has false positives :(

View File

@ -31,131 +31,6 @@ struct BuildIndices<offset, 0, T...>
using result = Indices<T...>;
};
template <typename... Types> struct Tuple;
template <> struct Tuple<> {};
template <typename Head, typename... Tail>
struct Tuple<Head, Tail...> : Tuple<Tail...>
{
Head value;
Tuple() {}
Tuple(Head head, Tail... tail) : Tuple<Tail...>(tail...), value(head) {}
Tuple(const Tuple<Head, Tail...>& rhs) : Tuple<Tail...>(rhs) { value = rhs.value; }
};
template <typename... Types>
auto makeTuple(Types... types)
{
return Tuple<Types...>(types...);
}
template <typename T> struct TupleSize;
template <typename... Types>
struct TupleSize<const Tuple<Types...> >
{
enum { result = sizeof...(Types) };
};
template <typename... Types>
struct TupleSize<Tuple<Types...> >
{
enum { result = sizeof...(Types) };
};
template <int Index, typename Tuple> struct TupleElement;
template <typename HeadType, typename... TailTypes>
struct TupleElement<0, const Tuple<HeadType, TailTypes...> >
{
using Head = HeadType;
using Tail = const Tuple<HeadType, TailTypes...>;
};
template <int Index, typename Head, typename... Tail>
struct TupleElement<Index, const Tuple<Head, Tail...> >
: TupleElement<Index - 1, const Tuple<Tail...> >
{
};
template <typename HeadType, typename... TailTypes>
struct TupleElement<0, Tuple<HeadType, TailTypes...> >
{
using Head = HeadType;
using Tail = Tuple<HeadType, TailTypes...>;
};
template <int Index, typename Head, typename... Tail>
struct TupleElement<Index, Tuple<Head, Tail...> >
: TupleElement<Index - 1, Tuple<Tail...> >
{
};
template <int Index, typename... Types>
constexpr auto& get(const Tuple<Types...>& tuple)
{
using Subtuple = typename TupleElement<Index, const ::Lumix::Tuple<Types...> >::Tail;
return (((Subtuple&)tuple).value);
}
template <int Index, typename... Types>
constexpr auto& get(Tuple<Types...>& tuple)
{
using Subtuple = typename TupleElement<Index, ::Lumix::Tuple<Types...> >::Tail;
return (((Subtuple&)tuple).value);
}
template <typename F, typename Tuple, int... I>
constexpr void apply_impl(F& f, Tuple& t, Indices<I...>)
{
using expand = bool[];
(void)expand
{
(
f(get<I>(t)),
true
)...
};
}
template <typename F, typename Tuple>
constexpr void apply_impl(F& f, Tuple& t, Indices<>) {}
template <typename F, typename Tuple>
constexpr void apply(F& f, Tuple& t)
{
apply_impl(f, t, typename BuildIndices<-1, TupleSize<Tuple>::result>::result{});
}
template <typename F, typename Tuple, int... I>
constexpr void apply_impl(const F& f, Tuple& t, Indices<I...>)
{
using expand = bool[];
(void)expand
{
(
f(get<I>(t)),
true
)...
};
}
template <typename F, typename Tuple>
constexpr void apply_impl(const F& f, Tuple& t, Indices<>) {}
template <typename F, typename Tuple>
constexpr void apply(const F& f, Tuple& t)
{
apply_impl(f, t, typename BuildIndices<-1, TupleSize<Tuple>::result>::result{});
}
template <typename T> struct ResultOf;
template <typename R, typename C, typename... Args> struct ResultOf<R(C::*)(Args...)> { using Type = R; };
@ -169,4 +44,10 @@ template <typename R, typename C, typename... Args> struct ClassOf<R(C::*)(Args.
template <typename R, typename C> struct ClassOf<R(C::*)> { using Type = C; };
template <typename T> struct ArgsCount;
template <typename R, typename C, typename... Args> struct ArgsCount<R(C::*)(Args...)> { static constexpr u32 value = sizeof...(Args); };
template <typename R, typename C, typename... Args> struct ArgsCount<R(C::*)(Args...)const > { static constexpr u32 value = sizeof...(Args); };
template <typename R, typename C> struct ArgsCount<R(C::*)> { static constexpr u32 value = 0; };
} // namespace Lumix

View File

@ -11,46 +11,10 @@ namespace Lumix
namespace reflection
{
template <> Path readFromStream<Path>(InputMemoryStream& stream)
{
const char* c_str = (const char*)stream.getData() + stream.getPosition();
Path path(c_str);
stream.skip(stringLength(c_str) + 1);
return path;
}
template <> void writeToStream<const Path&>(OutputMemoryStream& stream, const Path& path)
{
const char* str = path.c_str();
stream.write(str, stringLength(str) + 1);
}
template <> void writeToStream<Path>(OutputMemoryStream& stream, Path path)
{
const char* str = path.c_str();
stream.write(str, stringLength(str) + 1);
}
template <> const char* readFromStream<const char*>(InputMemoryStream& stream)
{
const char* c_str = (const char*)stream.getData() + stream.getPosition();
stream.skip(stringLength(c_str) + 1);
return c_str;
}
template <> void writeToStream<const char*>(OutputMemoryStream& stream, const char* value)
{
stream.write(value, stringLength(value) + 1);
}
struct Context {
SceneBase* first_scene = nullptr;
RegisteredComponent components[ComponentType::MAX_TYPES_COUNT];
Scene* first_scene = nullptr;
RegisteredComponent ComponentBases[ComponentType::MAX_TYPES_COUNT];
u32 components_count = 0;
};
@ -59,35 +23,61 @@ static Context& getContext() {
return ctx;
}
static IAllocator& getAllocator() {
static DefaultAllocator alloc;
return alloc;
}
Array<FunctionBase*>& allFunctions() {
static DefaultAllocator allocator;
static Array<FunctionBase*> fncs(allocator);
static Array<FunctionBase*> fncs(getAllocator());
return fncs;
}
const ComponentBase* getComponent(ComponentType cmp_type) {
return getContext().components[cmp_type.index].cmp;
}
ComponentBase::ComponentBase(IAllocator& allocator)
: props(allocator)
, functions(allocator)
{}
SceneBase* getFirstScene() { return getContext().first_scene; }
void registerScene(SceneBase& scene) {
Context& ctx = getContext();
scene.next = ctx.first_scene;
ctx.first_scene = &scene;
const u32 scene_name_hash = crc32(scene.name);
for (ComponentBase* cmp : scene.getComponents()) {
ctx.components[cmp->component_type.index].cmp = cmp;
ctx.components[cmp->component_type.index].scene = scene_name_hash;
void ComponentBase::visit(IPropertyVisitor& visitor) const {
for (const PropertyBase* prop : props) {
prop->visit(visitor);
}
}
const ComponentBase* getComponent(ComponentType cmp_type) {
return getContext().ComponentBases[cmp_type.index].cmp;
}
const PropertyBase* getProperty(ComponentType cmp_type, const char* prop_name) {
const ComponentBase* cmp = getComponent(cmp_type);
for (PropertyBase* prop : cmp->props) {
if (equalStrings(prop->name, prop_name)) return prop;
}
return nullptr;
}
Scene::Scene(IAllocator& allocator)
: cmps(allocator)
, functions(allocator)
{}
builder::builder(IAllocator& allocator)
: allocator(allocator)
{
scene = LUMIX_NEW(allocator, Scene)(allocator);
}
void builder::registerCmp(ComponentBase* cmp) {
getContext().ComponentBases[cmp->component_type.index].cmp = cmp;
getContext().ComponentBases[cmp->component_type.index].name_hash = crc32(cmp->name);
getContext().ComponentBases[cmp->component_type.index].scene = crc32(scene->name);
scene->cmps.push(cmp);
}
ComponentType getComponentTypeFromHash(u32 hash)
{
for (u32 i = 0, c = getContext().components_count; i < c; ++i) {
if (getContext().components[i].name_hash == hash) {
if (getContext().ComponentBases[i].name_hash == hash) {
return {(i32)i};
}
}
@ -98,35 +88,170 @@ ComponentType getComponentTypeFromHash(u32 hash)
u32 getComponentTypeHash(ComponentType type)
{
return getContext().components[type.index].name_hash;
return getContext().ComponentBases[type.index].name_hash;
}
ComponentType getComponentType(const char* name)
{
Context& ctx = getContext();
u32 name_hash = crc32(name);
for (u32 i = 0, c = getContext().components_count; i < c; ++i) {
if (getContext().components[i].name_hash == name_hash) {
for (u32 i = 0, c = ctx.components_count; i < c; ++i) {
if (ctx.ComponentBases[i].name_hash == name_hash) {
return {(i32)i};
}
}
if (getContext().components_count == ComponentType::MAX_TYPES_COUNT) {
if (ctx.components_count == ComponentType::MAX_TYPES_COUNT) {
logError("Too many component types");
return INVALID_COMPONENT_TYPE;
}
RegisteredComponent& type = getContext().components[getContext().components_count];
RegisteredComponent& type = ctx.ComponentBases[getContext().components_count];
type.name_hash = name_hash;
++getContext().components_count;
++ctx.components_count;
return {i32(getContext().components_count - 1)};
}
Span<const RegisteredComponent> getComponents() {
return Span(getContext().components, getContext().components_count);
Scene* getFirstScene() {
return getContext().first_scene;
}
Span<const RegisteredComponent> getComponents() {
return Span(getContext().ComponentBases, getContext().components_count);
}
struct RadiansAttribute : IAttribute
{
int getType() const override { return RADIANS; }
};
struct MultilineAttribute : IAttribute
{
int getType() const override { return MULTILINE; }
};
struct NoUIAttribute : IAttribute {
int getType() const override { return NO_UI; }
};
builder build_scene(const char* name) {
builder res(getAllocator());
Context& ctx = getContext();
res.scene->next = ctx.first_scene;
ctx.first_scene = res.scene;
res.scene->name = name;
return res;
}
builder& builder::radiansAttribute() {
auto* a = LUMIX_NEW(allocator, RadiansAttribute);
last_prop->attributes.push(a);
return *this;
}
builder& builder::colorAttribute() {
auto* a = LUMIX_NEW(allocator, ColorAttribute);
last_prop->attributes.push(a);
return *this;
}
builder& builder::noUIAttribute() {
auto* a = LUMIX_NEW(allocator, NoUIAttribute);
last_prop->attributes.push(a);
return *this;
}
builder& builder::multilineAttribute() {
auto* a = LUMIX_NEW(allocator, MultilineAttribute);
last_prop->attributes.push(a);
return *this;
}
builder& builder::minAttribute(float value) {
auto* a = LUMIX_NEW(allocator, MinAttribute)(value);
last_prop->attributes.push(a);
return *this;
}
builder& builder::clampAttribute(float min, float max) {
auto* a = LUMIX_NEW(allocator, ClampAttribute)(min, max);
last_prop->attributes.push(a);
return *this;
}
builder& builder::resourceAttribute(ResourceType type) {
auto* a = LUMIX_NEW(allocator, ResourceAttribute)(type);
last_prop->attributes.push(a);
return *this;
}
builder& builder::end_array() {
array = nullptr;
last_prop = nullptr;
return *this;
}
builder& builder::icon(const char* icon) {
scene->cmps.back()->icon = icon;
return *this;
}
void builder::addProp(PropertyBase* p) {
if (array) {
array->children.push(p);
}
else {
scene->cmps.back()->props.push(p);
}
last_prop = p;
}
BlobProperty::BlobProperty(IAllocator& allocator)
: PropertyBase(allocator)
{}
void BlobProperty::visit(struct IPropertyVisitor& visitor) const {
visitor.visit(*this);
}
void BlobProperty::getValue(ComponentUID cmp, u32 idx, OutputMemoryStream& stream) const {
getter(cmp.scene, (EntityRef)cmp.entity, idx, stream);
}
void BlobProperty::setValue(ComponentUID cmp, u32 idx, InputMemoryStream& stream) const {
setter(cmp.scene, (EntityRef)cmp.entity, idx, stream);
}
ArrayProperty::ArrayProperty(IAllocator& allocator)
: PropertyBase(allocator)
, children(allocator)
{}
u32 ArrayProperty::getCount(ComponentUID cmp) const {
return counter(cmp.scene, (EntityRef)cmp.entity);
}
void ArrayProperty::addItem(ComponentUID cmp, u32 idx) const {
adder(cmp.scene, (EntityRef)cmp.entity, idx);
}
void ArrayProperty::removeItem(ComponentUID cmp, u32 idx) const {
remover(cmp.scene, (EntityRef)cmp.entity, idx);
}
void ArrayProperty::visit(struct IPropertyVisitor& visitor) const {
visitor.visit(*this);
}
void ArrayProperty::visitChildren(struct IPropertyVisitor& visitor) const {
for (PropertyBase* prop : children) {
prop->visit(visitor);
}
}
} // namespace Reflection

View File

@ -4,21 +4,16 @@
#include "engine/lumix.h"
#include "engine/metaprogramming.h"
#include "engine/resource.h"
#include "engine/stream.h"
#include "engine/universe.h"
#define LUMIX_CMP(Component, ...) component<&ReflScene::create##Component, &ReflScene::destroy##Component>(__VA_ARGS__)
#define LUMIX_PROP(Property, Label, ...) property(Label, &ReflScene::get##Property, &ReflScene::set##Property, ##__VA_ARGS__)
#define LUMIX_FUNC_EX(Func, Name) reflection::function(&Func, #Func, Name)
#define LUMIX_FUNC(Func) reflection::function(&Func, #Func, nullptr)
#define LUMIX_SCENE(Type, Name, ...) \
do { \
using namespace reflection; \
static auto registered_scene = [](){ using ReflScene = Type; return reflection::scene(Name, ##__VA_ARGS__); }(); \
reflection::registerScene(registered_scene); \
} while(false)
#define LUMIX_SCENE(Class, Label) using ReflScene = Class; reflection::build_scene(Label)
#define LUMIX_FUNC_EX(F, Name) function<&ReflScene::F>(Name, #F)
#define LUMIX_FUNC(F) function<&F>(#F, #F)
#define LUMIX_CMP(Cmp, Name, Label) cmp<&ReflScene::create##Cmp, &ReflScene::destroy##Cmp>(Name, Label)
#define LUMIX_PROP(Property, Label) prop<&ReflScene::get##Property, &ReflScene::set##Property>(Label)
#define LUMIX_ENUM_PROP(Property, Label) enum_prop<&ReflScene::get##Property, &ReflScene::set##Property>(Label)
#define LUMIX_GLOBAL_FUNC(Func) reflection::function(&Func, #Func, nullptr)
namespace Lumix
{
@ -52,9 +47,6 @@ struct IAttribute {
virtual int getType() const = 0;
};
struct ComponentBase;
struct SceneBase;
// we don't use method pointers here because VS has sizeof issues if IScene is forward declared
using CreateComponent = void (*)(IScene*, EntityRef);
using DestroyComponent = void (*)(IScene*, EntityRef);
@ -62,26 +54,16 @@ using DestroyComponent = void (*)(IScene*, EntityRef);
struct RegisteredComponent {
u32 name_hash = 0;
u32 scene = 0;
ComponentBase* cmp = nullptr;
struct ComponentBase* cmp = nullptr;
};
LUMIX_ENGINE_API void registerScene(SceneBase& scene);
LUMIX_ENGINE_API SceneBase* getFirstScene();
LUMIX_ENGINE_API const ComponentBase* getComponent(ComponentType cmp_type);
LUMIX_ENGINE_API const struct PropertyBase* getProperty(ComponentType cmp_type, const char* prop);
LUMIX_ENGINE_API Span<const RegisteredComponent> getComponents();
LUMIX_ENGINE_API ComponentType getComponentType(const char* id);
LUMIX_ENGINE_API ComponentType getComponentTypeFromHash(u32 hash);
template <typename T> void writeToStream(OutputMemoryStream& stream, T value) { stream.write(value); }
template <typename T> T readFromStream(InputMemoryStream& stream) { return stream.read<T>(); }
template <> LUMIX_ENGINE_API Path readFromStream<Path>(InputMemoryStream& stream);
template <> LUMIX_ENGINE_API void writeToStream<Path>(OutputMemoryStream& stream, Path);
template <> LUMIX_ENGINE_API void writeToStream<const Path&>(OutputMemoryStream& stream, const Path& path);
template <> LUMIX_ENGINE_API const char* readFromStream<const char*>(InputMemoryStream& stream);
template <> LUMIX_ENGINE_API void writeToStream<const char*>(OutputMemoryStream& stream, const char* path);
struct ResourceAttribute : IAttribute
{
ResourceAttribute(ResourceType type) : resource_type(type) {}
@ -113,6 +95,10 @@ struct ClampAttribute : IAttribute
float max;
};
struct ColorAttribute : IAttribute {
int getType() const override { return COLOR; }
};
struct EnumAttribute : IAttribute {
virtual u32 count(ComponentUID cmp) const = 0;
virtual const char* name(ComponentUID cmp, u32 idx) const = 0;
@ -127,41 +113,17 @@ struct StringEnumAttribute : IAttribute {
int getType() const override { return STRING_ENUM; }
};
struct RadiansAttribute : IAttribute
{
int getType() const override { return RADIANS; }
};
struct MultilineAttribute : IAttribute
{
int getType() const override { return MULTILINE; }
};
struct PropertyBase {
PropertyBase(IAllocator& allocator) : attributes(allocator) {}
Array<IAttribute*> attributes;
struct ColorAttribute : IAttribute
{
int getType() const override { return COLOR; }
};
struct NoUIAttribute : IAttribute {
int getType() const override { return NO_UI; }
};
struct PropertyTag {};
template <typename T> struct Property : PropertyTag {
virtual Span<const IAttribute* const> getAttributes() const = 0;
virtual T get(ComponentUID cmp, int index) const = 0;
virtual void set(ComponentUID cmp, int index, T) const = 0;
virtual void visit(struct IPropertyVisitor& visitor) const = 0;
const char* name;
};
struct IBlobProperty : PropertyTag {
virtual void getValue(ComponentUID cmp, int index, OutputMemoryStream& stream) const = 0;
virtual void setValue(ComponentUID cmp, int index, InputMemoryStream& stream) const = 0;
const char* name;
};
struct IDynamicProperties : PropertyTag {
struct DynamicProperties : PropertyBase {
enum Type {
I32,
FLOAT,
@ -182,47 +144,60 @@ struct IDynamicProperties : PropertyTag {
bool b;
Vec3 v3;
};
DynamicProperties(IAllocator& allocator) : PropertyBase(allocator) {}
virtual u32 getCount(ComponentUID cmp, int array_idx) const = 0;
virtual Type getType(ComponentUID cmp, int array_idx, u32 idx) const = 0;
virtual const char* getName(ComponentUID cmp, int array_idx, u32 idx) const = 0;
virtual Value getValue(ComponentUID cmp, int array_idx, u32 idx) const = 0;
virtual reflection::ResourceAttribute getResourceAttribute(ComponentUID cmp, int array_idx, u32 idx) const = 0;
virtual ResourceAttribute getResourceAttribute(ComponentUID cmp, int array_idx, u32 idx) const = 0;
virtual void set(ComponentUID cmp, int array_idx, const char* name, Type type, Value value) const = 0;
virtual void set(ComponentUID cmp, int array_idx, u32 idx, Value value) const = 0;
const char* name;
};
template <typename T> inline T get(IDynamicProperties::Value);
template <> inline float get(IDynamicProperties::Value v) { return v.f; }
template <> inline i32 get(IDynamicProperties::Value v) { return v.i; }
template <> inline const char* get(IDynamicProperties::Value v) { return v.s; }
template <> inline EntityPtr get(IDynamicProperties::Value v) { return v.e; }
template <> inline bool get(IDynamicProperties::Value v) { return v.b; }
template <> inline Vec3 get(IDynamicProperties::Value v) { return v.v3; }
template <typename T> inline void set(IDynamicProperties::Value& v, T);
template <> inline void set(IDynamicProperties::Value& v, float val) { v.f = val; }
template <> inline void set(IDynamicProperties::Value& v, i32 val) { v.i = val; }
template <> inline void set(IDynamicProperties::Value& v, const char* val) { v.s = val; }
template <> inline void set(IDynamicProperties::Value& v, EntityPtr val) { v.e = val; }
template <> inline void set(IDynamicProperties::Value& v, bool val) { v.b = val; }
template <> inline void set(IDynamicProperties::Value& v, Vec3 val) { v.v3 = val; }
struct IArrayProperty : PropertyTag
{
virtual void addItem(ComponentUID cmp, int index) const = 0;
virtual void removeItem(ComponentUID cmp, int index) const = 0;
virtual int getCount(ComponentUID cmp) const = 0;
virtual void visit(struct IPropertyVisitor& visitor) const = 0;
const char* name;
};
struct IPropertyVisitor
{
virtual ~IPropertyVisitor() {}
template <typename T> inline T get(DynamicProperties::Value);
template <> inline float get(DynamicProperties::Value v) { return v.f; }
template <> inline i32 get(DynamicProperties::Value v) { return v.i; }
template <> inline const char* get(DynamicProperties::Value v) { return v.s; }
template <> inline EntityPtr get(DynamicProperties::Value v) { return v.e; }
template <> inline bool get(DynamicProperties::Value v) { return v.b; }
template <> inline Vec3 get(DynamicProperties::Value v) { return v.v3; }
template <typename T> inline void set(DynamicProperties::Value& v, T);
template <> inline void set(DynamicProperties::Value& v, float val) { v.f = val; }
template <> inline void set(DynamicProperties::Value& v, i32 val) { v.i = val; }
template <> inline void set(DynamicProperties::Value& v, const char* val) { v.s = val; }
template <> inline void set(DynamicProperties::Value& v, EntityPtr val) { v.e = val; }
template <> inline void set(DynamicProperties::Value& v, bool val) { v.b = val; }
template <> inline void set(DynamicProperties::Value& v, Vec3 val) { v.v3 = val; }
template <typename T>
struct Property : PropertyBase {
Property(IAllocator& allocator) : PropertyBase(allocator) {}
typedef void (*Setter)(IScene*, EntityRef, u32, const T&);
typedef T (*Getter)(IScene*, EntityRef, u32);
void visit(IPropertyVisitor& visitor) const override {
visitor.visit(*this);
}
virtual T get(ComponentUID cmp, u32 idx) const {
return getter(cmp.scene, (EntityRef)cmp.entity, idx);
}
virtual void set(ComponentUID cmp, u32 idx, T val) const {
setter(cmp.scene, (EntityRef)cmp.entity, idx, val);
}
Setter setter;
Getter getter;
};
struct IPropertyVisitor {
virtual ~IPropertyVisitor() {}
virtual void visit(const Property<float>& prop) = 0;
virtual void visit(const Property<int>& prop) = 0;
virtual void visit(const Property<u32>& prop) = 0;
@ -234,13 +209,13 @@ struct IPropertyVisitor
virtual void visit(const Property<Path>& prop) = 0;
virtual void visit(const Property<bool>& prop) = 0;
virtual void visit(const Property<const char*>& prop) = 0;
virtual void visit(const IDynamicProperties& prop) {}
virtual void visit(const IArrayProperty& prop) = 0;
virtual void visit(const IBlobProperty& prop) = 0;
virtual void visit(const struct ArrayProperty& prop) = 0;
virtual void visit(const struct BlobProperty& prop) = 0;
virtual void visit(const DynamicProperties& prop) {}
};
struct IEmptyPropertyVisitor : IPropertyVisitor
{
struct IEmptyPropertyVisitor : IPropertyVisitor {
virtual ~IEmptyPropertyVisitor() {}
void visit(const Property<float>& prop) override {}
void visit(const Property<int>& prop) override {}
void visit(const Property<u32>& prop) override {}
@ -252,25 +227,43 @@ struct IEmptyPropertyVisitor : IPropertyVisitor
void visit(const Property<Path>& prop) override {}
void visit(const Property<bool>& prop) override {}
void visit(const Property<const char*>& prop) override {}
void visit(const IArrayProperty& prop) override {}
void visit(const IBlobProperty& prop) override {}
void visit(const IDynamicProperties& prop) override {}
void visit(const ArrayProperty& prop) override {}
void visit(const BlobProperty& prop) override {}
void visit(const DynamicProperties& prop) override {}
};
struct ComponentBase
{
virtual ~ComponentBase() {}
struct LUMIX_ENGINE_API ArrayProperty : PropertyBase {
typedef u32 (*Counter)(IScene*, EntityRef);
typedef void (*Adder)(IScene*, EntityRef, u32);
typedef void (*Remover)(IScene*, EntityRef, u32);
virtual int getPropertyCount() const = 0;
virtual void visit(IPropertyVisitor&) const = 0;
virtual Span<const struct FunctionBase* const> getFunctions() const = 0;
ArrayProperty(IAllocator& allocator);
const char* name;
const char* label;
const char* icon = "";
CreateComponent creator;
DestroyComponent destroyer;
ComponentType component_type;
u32 getCount(ComponentUID cmp) const;
void addItem(ComponentUID cmp, u32 idx) const;
void removeItem(ComponentUID cmp, u32 idx) const;
void visit(struct IPropertyVisitor& visitor) const override;
void visitChildren(struct IPropertyVisitor& visitor) const;
Array<PropertyBase*> children;
Counter counter;
Adder adder;
Remover remover;
};
struct LUMIX_ENGINE_API BlobProperty : PropertyBase {
BlobProperty(IAllocator& allocator);
void visit(struct IPropertyVisitor& visitor) const override;
void getValue(ComponentUID cmp, u32 idx, OutputMemoryStream& stream) const;
void setValue(ComponentUID cmp, u32 idx, InputMemoryStream& stream) const;
typedef void (*Getter)(IScene*, EntityRef, u32, OutputMemoryStream&);
typedef void (*Setter)(IScene*, EntityRef, u32, InputMemoryStream&);
Getter getter;
Setter setter;
};
struct Icon { const char* name; };
@ -294,98 +287,15 @@ bool getPropertyValue(IScene& scene, EntityRef e, ComponentType cmp_type, const
visitor.cmp.scene = &scene;
visitor.cmp.type = cmp_type;
visitor.cmp.entity = e;
const reflection::ComponentBase* cmp_desc = getComponent(cmp_type);
const ComponentBase* cmp_desc = getComponent(cmp_type);
cmp_desc->visit(visitor);
out = visitor.value;
return visitor.found;
}
template <typename Base, typename... T>
struct TupleHolder {
TupleHolder() {}
TupleHolder(Tuple<T...> tuple) { init(tuple); }
TupleHolder(TupleHolder&& rhs) { init(rhs.objects); }
TupleHolder(const TupleHolder& rhs) { init(rhs.objects); }
void init(const Tuple<T...>& tuple)
{
objects = tuple;
int i = 0;
apply([&](auto& v){
ptrs[i] = &v;
++i;
}, objects);
}
void operator =(Tuple<T...>&& tuple) { init(tuple); }
void operator =(const TupleHolder& rhs) { init(rhs.objects); }
void operator =(TupleHolder&& rhs) { init(rhs.objects); }
Span<const Base* const> get() const {
return Span(static_cast<const Base*const*>(ptrs), (u32)sizeof...(T));
}
Span<Base* const> get() {
return Span(static_cast<Base*const*>(ptrs), (u32)sizeof...(T));
}
Tuple<T...> objects;
Base* ptrs[sizeof...(T) + 1];
};
template <typename Getter, typename Setter>
struct BlobProperty : IBlobProperty
{
void getValue(ComponentUID cmp, int index, OutputMemoryStream& stream) const override
{
using C = typename ClassOf<Getter>::Type;
C* inst = static_cast<C*>(cmp.scene);
(inst->*getter)((EntityRef)cmp.entity, stream);
}
void setValue(ComponentUID cmp, int index, InputMemoryStream& stream) const override
{
using C = typename ClassOf<Getter>::Type;
C* inst = static_cast<C*>(cmp.scene);
(inst->*setter)((EntityRef)cmp.entity, stream);
}
Getter getter;
Setter setter;
};
template <typename T, typename CmpGetter, typename PtrType, typename... Attributes>
struct VarProperty : Property<T>
{
Span<const IAttribute* const> getAttributes() const override { return attributes.get(); }
T get(ComponentUID cmp, int index) const override
{
using C = typename ClassOf<CmpGetter>::Type;
C* inst = static_cast<C*>(cmp.scene);
auto& c = (inst->*cmp_getter)((EntityRef)cmp.entity);
auto& v = c.*ptr;
return static_cast<T>(v);
}
void set(ComponentUID cmp, int index, T value) const override
{
using C = typename ClassOf<CmpGetter>::Type;
C* inst = static_cast<C*>(cmp.scene);
auto& c = (inst->*cmp_getter)((EntityRef)cmp.entity);
c.*ptr = value;
}
CmpGetter cmp_getter;
PtrType ptr;
TupleHolder<IAttribute, Attributes...> attributes;
};
namespace detail {
static const unsigned int FRONT_SIZE = sizeof("Lumix::reflection::detail::GetTypeNameHelper<") - 1u;
static const unsigned int FRONT_SIZE = sizeof("Lumix::detail::GetTypeNameHelper<") - 1u;
static const unsigned int BACK_SIZE = sizeof(">::GetTypeName") - 1u;
template <typename T>
@ -406,124 +316,12 @@ struct GetTypeNameHelper
}
};
template <typename Getter> struct GetterProxy;
template <typename R, typename C>
struct GetterProxy<R(C::*)(EntityRef, int)>
{
using Getter = R(C::*)(EntityRef, int);
static R invoke(C* inst, Getter getter, EntityRef entity, int index)
{
return (inst->*getter)(entity, index);
}
};
template <typename R, typename C>
struct GetterProxy<R(C::*)(EntityRef)>
{
using Getter = R(C::*)(EntityRef);
static R invoke(C* inst, Getter getter, EntityRef entity, int index)
{
return (inst->*getter)(entity);
}
};
template <typename Setter> struct SetterProxy;
template <typename C, typename A>
struct SetterProxy<void (C::*)(EntityRef, int, A)>
{
using Setter = void (C::*)(EntityRef, int, A);
template <typename T>
static void invoke(C* inst, Setter setter, EntityRef entity, int index, T value)
{
(inst->*setter)(entity, index, static_cast<A>(value));
}
};
template <typename C, typename A>
struct SetterProxy<void (C::*)(EntityRef, A)>
{
using Setter = void (C::*)(EntityRef, A);
template <typename T>
static void invoke(C* inst, Setter setter, EntityRef entity, int index, T value)
{
(inst->*setter)(entity, static_cast<A>(value));
}
};
} // namespace detail
template <typename T, typename Getter, typename Setter, typename... Attributes>
struct CommonProperty : Property<T>
{
Span<const IAttribute* const> getAttributes() const override { return attributes.get(); }
T get(ComponentUID cmp, int index) const override
{
using C = typename ClassOf<Getter>::Type;
C* inst = static_cast<C*>(cmp.scene);
return static_cast<T>(detail::GetterProxy<Getter>::invoke(inst, getter, (EntityRef)cmp.entity, index));
}
void set(ComponentUID cmp, int index, T value) const override
{
using C = typename ClassOf<Getter>::Type;
C* inst = static_cast<C*>(cmp.scene);
detail::SetterProxy<Setter>::invoke(inst, setter, (EntityRef)cmp.entity, index, value);
}
TupleHolder<IAttribute, Attributes...> attributes;
Getter getter;
Setter setter;
};
template <typename Counter, typename Adder, typename Remover, typename... Props>
struct ArrayProperty : IArrayProperty
{
ArrayProperty() {}
void addItem(ComponentUID cmp, int index) const override
{
using C = typename ClassOf<Counter>::Type;
C* inst = static_cast<C*>(cmp.scene);
(inst->*adder)((EntityRef)cmp.entity, index);
}
void removeItem(ComponentUID cmp, int index) const override
{
using C = typename ClassOf<Counter>::Type;
C* inst = static_cast<C*>(cmp.scene);
(inst->*remover)((EntityRef)cmp.entity, index);
}
int getCount(ComponentUID cmp) const override
{
using C = typename ClassOf<Counter>::Type;
C* inst = static_cast<C*>(cmp.scene);
return (inst->*counter)((EntityRef)cmp.entity);
}
void visit(IPropertyVisitor& visitor) const override
{
apply([&](auto& x) { visitor.visit(x); }, properties);
}
Tuple<Props...> properties;
Counter counter;
Adder adder;
Remover remover;
};
template <typename T>
const IAttribute* getAttribute(const Property<T>& prop, IAttribute::Type type) {
for (const IAttribute* attr : prop.getAttributes()) {
for (const IAttribute* attr : prop.attributes) {
if (attr->getType() == type) return attr;
}
return nullptr;
@ -590,117 +388,6 @@ struct FunctionBase
const char* name;
};
struct SceneBase
{
virtual ~SceneBase() {}
virtual Span<const FunctionBase* const> getFunctions() const = 0;
virtual Span<ComponentBase* const> getComponents() = 0;
const char* name;
SceneBase* next = nullptr;
};
template <typename Components, typename Funcs> struct Scene;
template <typename... Components, typename... Funcs>
struct Scene<Tuple<Components...>, Tuple<Funcs...>> : SceneBase
{
Span<const FunctionBase* const> getFunctions() const override { return functions.get(); }
Span<ComponentBase* const> getComponents() override { return components.get(); }
TupleHolder<ComponentBase, Components...> components;
TupleHolder<FunctionBase, Funcs...> functions;
};
template <typename Funcs, typename Props> struct Component;
template <typename... Funcs, typename Props>
struct Component<Tuple<Funcs...>, Props> : ComponentBase
{
int getPropertyCount() const override { return TupleSize<Props>::result; }
void visit(IPropertyVisitor& visitor) const override
{
apply([&](auto& x) { visitor.visit(x); }, properties);
}
Span<const FunctionBase* const> getFunctions() const override { return functions.get(); }
Props properties;
TupleHolder<FunctionBase, Funcs...> functions;
};
template <typename... T>
struct Filter {
template <typename B>
struct HasBase {
static u8 check(const void*) { return {}; }
static u32 check(const B*) { return {}; }
template <typename T2>
static constexpr bool has() { return sizeof(check((T2*)nullptr)) == sizeof(u32); }
};
static auto properties(T... t) { return makeTuple(t...); }
static auto functions(T... t) { return makeTuple(t...); }
static auto components(T... t) { return makeTuple(t...); }
template <typename... T2, typename H>
static auto properties(T... t, H h, T2... t2) {
if constexpr (HasBase<PropertyTag>::template has<H>()) {
return Filter<T..., H>::properties(t..., h, t2...);
}
else {
return Filter<T...>::properties(t..., t2...);
}
}
template <typename... T2, typename H>
static auto functions(T... t, H h, T2... t2) {
if constexpr (HasBase<FunctionBase>::template has<H>()) {
return Filter<T..., H>::functions(t..., h, t2...);
}
else {
return Filter<T...>::functions(t..., t2...);
}
}
template <typename... T2, typename H>
static auto components(T... t, H h, T2... t2) {
if constexpr (HasBase<ComponentBase>::template has<H>()) {
return Filter<T..., H>::components(t..., h, t2...);
}
else {
return Filter<T...>::components(t..., t2...);
}
}
static const char* icon() { return ""; }
template <typename H, typename... T2> static const char* icon(H h, T2... t) {
if constexpr (HasBase<Icon>::template has<H>()) {
return h.name;
}
else {
return icon(t...);
}
}
};
template <typename... Members>
auto scene(const char* name, Members... members)
{
using ComponentsTuple = decltype(Filter<>::components(members...));
using FunctionsTuple = decltype(Filter<>::functions(members...));
Scene<ComponentsTuple, FunctionsTuple> scene;
scene.name = name;
scene.functions = Filter<>::functions(members...);
scene.components = Filter<>::components(members...);
return scene;
}
template <typename T> struct VariantTag {};
template <typename T> inline Variant::Type _getVariantType(VariantTag<T*>) { return Variant::PTR; }
@ -818,89 +505,207 @@ auto& function(F func, const char* decl_code, const char* name)
return ret;
}
struct ComponentBase {
ComponentBase(IAllocator& allocator);
template <auto Creator, auto Destroyer, typename... Props>
auto component(const char* name, const char* label, Props... props)
{
auto creator = [](IScene* scene, EntityRef e){ (scene->*static_cast<void (IScene::*)(EntityRef)>(Creator))(e); };
auto destroyer = [](IScene* scene, EntityRef e){ (scene->*static_cast<void (IScene::*)(EntityRef)>(Destroyer))(e); };
void visit(IPropertyVisitor& visitor) const;
const char* icon = "";
const char* name;
const char* label;
u32 scene;
CreateComponent creator;
DestroyComponent destroyer;
ComponentType component_type;
Array<PropertyBase*> props;
Array<FunctionBase*> functions;
};
struct Scene {
Scene(IAllocator& allocator);
Array<FunctionBase*> functions;
Array<ComponentBase*> cmps;
const char* name;
Scene* next = nullptr;
};
LUMIX_ENGINE_API Scene* getFirstScene();
struct builder {
builder(IAllocator& allocator);
template <auto Creator, auto Destroyer>
builder& cmp(const char* name, const char* label) {
auto creator = [](IScene* scene, EntityRef e){ (scene->*static_cast<void (IScene::*)(EntityRef)>(Creator))(e); };
auto destroyer = [](IScene* scene, EntityRef e){ (scene->*static_cast<void (IScene::*)(EntityRef)>(Destroyer))(e); };
using PropsTuple = decltype(Filter<>::properties(props...));
using FuncsTuple = decltype(Filter<>::functions(props...));
ComponentBase* cmp = LUMIX_NEW(allocator, ComponentBase)(allocator);
cmp->name = name;
cmp->label = label;
cmp->component_type = getComponentType(name);
cmp->creator = creator;
cmp->destroyer = destroyer;
cmp->scene = crc32(scene->name);
registerCmp(cmp);
Component<FuncsTuple, PropsTuple> cmp;
cmp.creator = (CreateComponent)creator;
cmp.destroyer = (DestroyComponent)destroyer;
cmp.label = label;
cmp.name = name;
cmp.icon = Filter<>::icon(props...);
cmp.functions = Filter<>::functions(props...);
cmp.properties = Filter<>::properties(props...);
cmp.component_type = getComponentType(name);
return cmp;
}
return *this;
}
template <typename Getter, typename Setter>
auto blob_property(const char* name, Getter getter, Setter setter)
{
BlobProperty<Getter, Setter> p;
p.getter = getter;
p.setter = setter;
p.name = name;
return p;
}
template <auto Getter, auto Setter>
builder& enum_prop(const char* name) {
auto* p = LUMIX_NEW(allocator, Property<i32>)(allocator);
p->setter = [](IScene* scene, EntityRef e, u32 idx, const i32& value) {
using T = typename ResultOf<decltype(Getter)>::Type;
using C = typename ClassOf<decltype(Setter)>::Type;
if constexpr (ArgsCount<decltype(Setter)>::value == 2) {
(static_cast<C*>(scene)->*Setter)(e, static_cast<T>(value));
}
else {
(static_cast<C*>(scene)->*Setter)(e, idx, static_cast<T>(value));
}
};
template <typename CmpGetter, typename PtrType, typename... Attributes>
auto var_property(const char* name, CmpGetter getter, PtrType ptr, Attributes... attributes)
{
using T = typename ResultOf<PtrType>::Type;
VarProperty<T, CmpGetter, PtrType, Attributes...> p;
p.attributes = makeTuple(attributes...);
p.cmp_getter = getter;
p.ptr = ptr;
p.name = name;
return p;
}
p->getter = [](IScene* scene, EntityRef e, u32 idx) -> i32 {
using T = typename ResultOf<decltype(Getter)>::Type;
using C = typename ClassOf<decltype(Getter)>::Type;
if constexpr (ArgsCount<decltype(Getter)>::value == 1) {
return static_cast<i32>((static_cast<C*>(scene)->*Getter)(e));
}
else {
return static_cast<i32>((static_cast<C*>(scene)->*Getter)(e, idx));
}
};
p->name = name;
addProp(p);
return *this;
}
template <auto Getter, auto Setter>
builder& prop(const char* name) {
using T = typename ResultOf<decltype(Getter)>::Type;
auto* p = LUMIX_NEW(allocator, Property<T>)(allocator);
p->setter = [](IScene* scene, EntityRef e, u32 idx, const T& value) {
using C = typename ClassOf<decltype(Setter)>::Type;
if constexpr (ArgsCount<decltype(Setter)>::value == 2) {
(static_cast<C*>(scene)->*Setter)(e, value);
}
else {
(static_cast<C*>(scene)->*Setter)(e, idx, value);
}
};
p->getter = [](IScene* scene, EntityRef e, u32 idx) -> T {
using C = typename ClassOf<decltype(Getter)>::Type;
if constexpr (ArgsCount<decltype(Getter)>::value == 1) {
return (static_cast<C*>(scene)->*Getter)(e);
}
else {
return (static_cast<C*>(scene)->*Getter)(e, idx);
}
};
p->name = name;
addProp(p);
return *this;
}
template <auto Getter, auto PropGetter>
builder& blob_property(const char* name) {
auto* p = LUMIX_NEW(allocator, BlobProperty)(allocator);
p->name = name;
addProp(p);
return *this;
}
template <auto Getter, auto PropGetter>
builder& var_prop(const char* name) {
using T = typename ResultOf<decltype(PropGetter)>::Type;
auto* p = LUMIX_NEW(allocator, Property<T>)(allocator);
p->setter = [](IScene* scene, EntityRef e, u32, const T& value) {
using C = typename ClassOf<decltype(Getter)>::Type;
auto& c = (static_cast<C*>(scene)->*Getter)(e);
auto& v = c.*PropGetter;
v = value;
};
p->getter = [](IScene* scene, EntityRef e, u32) -> T {
using C = typename ClassOf<decltype(Getter)>::Type;
auto& c = (static_cast<C*>(scene)->*Getter)(e);
auto& v = c.*PropGetter;
return static_cast<T>(v);
};
p->name = name;
addProp(p);
return *this;
}
template <typename Getter, typename Setter, typename... Attributes>
auto property(const char* name, Getter getter, Setter setter, Attributes... attributes)
{
using R = typename ResultOf<Getter>::Type;
CommonProperty<R, Getter, Setter, Attributes...> p;
p.attributes = makeTuple(attributes...);
p.getter = getter;
p.setter = setter;
p.name = name;
return p;
}
template <auto Counter, auto Adder, auto Remover>
builder& begin_array(const char* name) {
ArrayProperty* prop = LUMIX_NEW(allocator, ArrayProperty)(allocator);
using C = typename ClassOf<decltype(Counter)>::Type;
prop->counter = [](IScene* scene, EntityRef e) -> u32 {
return (static_cast<C*>(scene)->*Counter)(e);
};
prop->adder = [](IScene* scene, EntityRef e, u32 idx) {
(static_cast<C*>(scene)->*Adder)(e, idx);
};
prop->remover = [](IScene* scene, EntityRef e, u32 idx) {
(static_cast<C*>(scene)->*Remover)(e, idx);
};
prop->name = name;
scene->cmps.back()->props.push(prop);
array = prop;
last_prop = prop;
return *this;
}
template <typename Getter, typename Setter, typename... Attributes>
auto enum_property(const char* name, Getter getter, Setter setter, Attributes... attributes)
{
using R = typename ResultOf<Getter>::Type;
CommonProperty<i32, Getter, Setter, Attributes...> p;
p.attributes = makeTuple(attributes...);
p.getter = getter;
p.setter = setter;
p.name = name;
return p;
}
template <typename T>
builder& attribute() {
auto* a = LUMIX_NEW(allocator, T);
last_prop->attributes.push(a);
return *this;
}
template <typename Counter, typename Adder, typename Remover, typename... Props>
auto array(const char* name, Counter counter, Adder adder, Remover remover, Props... properties)
{
ArrayProperty<Counter, Adder, Remover, Props...> p;
p.name = name;
p.counter = counter;
p.adder = adder;
p.remover = remover;
p.properties = makeTuple(properties...);
return p;
}
template <auto F>
builder& function(const char* name, const char* decl_code) {
auto* f = LUMIX_NEW(allocator, Function<decltype(F)>);
f->function = F;
f->name = name;
f->decl_code = decl_code;
if (scene->cmps.empty()) {
scene->functions.push(f);
}
else {
scene->cmps.back()->functions.push(f);
}
return *this;
}
void registerCmp(ComponentBase* cmp);
} // namespace Reflection
builder& minAttribute(float value);
builder& clampAttribute(float min, float max);
builder& resourceAttribute(ResourceType type);
builder& radiansAttribute();
builder& colorAttribute();
builder& noUIAttribute();
builder& multilineAttribute();
builder& icon(const char* icon);
builder& end_array();
void addProp(PropertyBase* prop);
IAllocator& allocator;
Scene* scene;
ArrayProperty* array = nullptr;
PropertyBase* last_prop = nullptr;
};
builder build_scene(const char* scene_name);
} // namespace reflection
} // namespace Lumix

View File

@ -5,6 +5,23 @@
namespace Lumix
{
bool isLetter(char c)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
bool isNumeric(char c)
{
return c >= '0' && c <= '9';
}
bool isUpperCase(char c)
{
return c >= 'A' && c <= 'Z';
}
String::String(IAllocator& allocator)

View File

@ -51,25 +51,9 @@ LUMIX_ENGINE_API int compareStringN(const char* lhs, const char* rhs, int length
LUMIX_ENGINE_API int compareIStringN(const char* lhs, const char* rhs, int length);
LUMIX_ENGINE_API const char* findSubstring(const char* str, const char* substr);
LUMIX_ENGINE_API bool endsWith(const char* str, const char* substr);
inline bool isLetter(char c)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
inline bool isNumeric(char c)
{
return c >= '0' && c <= '9';
}
inline bool isUpperCase(char c)
{
return c >= 'A' && c <= 'Z';
}
LUMIX_ENGINE_API bool isLetter(char c);
LUMIX_ENGINE_API bool isNumeric(char c);
LUMIX_ENGINE_API bool isUpperCase(char c);
template <int SIZE> bool copyString(char(&destination)[SIZE], const char* source)
{

View File

@ -1,12 +1,6 @@
#include "engine/controller_device.h"
#include "engine/allocator.h"
#define NOGDI
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <Xinput.h>
#include "engine/win/simple_win.h"
namespace Lumix
{
@ -101,13 +95,13 @@ void ControllerDevice::init(InputSystem& input_system)
g_controllers.input = &input_system;
g_controllers.last_checked = 0;
g_controllers.lib = LoadLibrary("Xinput9_1_0.dll");
g_controllers.lib = os::loadLibrary("Xinput9_1_0.dll");
if (g_controllers.lib)
{
g_controllers.get_state = (XInputGetState_fn_ptr)GetProcAddress(g_controllers.lib, "XInputGetState");
g_controllers.get_state = (XInputGetState_fn_ptr)os::getLibrarySymbol(g_controllers.lib, "XInputGetState");
if (!g_controllers.get_state)
{
FreeLibrary(g_controllers.lib);
os::unloadLibrary(g_controllers.lib);
g_controllers.lib = nullptr;
}
}
@ -145,7 +139,7 @@ void ControllerDevice::frame(float dt)
void ControllerDevice::shutdown()
{
if (g_controllers.lib) FreeLibrary(g_controllers.lib);
if (g_controllers.lib) os::unloadLibrary(g_controllers.lib);
}

View File

@ -4,6 +4,8 @@
#ifndef _W64
#define _W64 __w64
#endif
#define ERROR_SUCCESS 0L
#define XUSER_MAX_COUNT 4
#define MEM_COMMIT 0x00001000
#define MEM_RESERVE 0x00002000
#define MEM_RELEASE 0x00008000
@ -277,8 +279,26 @@ struct sockaddr_in
typedef UINT_PTR SOCKET;
typedef unsigned short WORD;
typedef short SHORT;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct _XINPUT_GAMEPAD
{
WORD wButtons;
BYTE bLeftTrigger;
BYTE bRightTrigger;
SHORT sThumbLX;
SHORT sThumbLY;
SHORT sThumbRX;
SHORT sThumbRY;
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
typedef struct _XINPUT_STATE
{
DWORD dwPacketNumber;
XINPUT_GAMEPAD Gamepad;
} XINPUT_STATE, *PXINPUT_STATE;
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
@ -346,6 +366,11 @@ typedef struct tagWNDCLASSEXA
} WNDCLASSEXA, *PWNDCLASSEXA, *NPWNDCLASSEXA, *LPWNDCLASSEXA;
typedef WNDCLASSEXA WNDCLASSEX;
typedef PWNDCLASSEXA PWNDCLASSEX;
typedef enum PROCESS_DPI_AWARENESS {
PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2
} PROCESS_DPI_AWARENESS;
typedef struct _SYSTEM_INFO
@ -369,6 +394,7 @@ typedef struct _SYSTEM_INFO
WORD wProcessorRevision;
} SYSTEM_INFO, *LPSYSTEM_INFO;
typedef long HRESULT;
typedef struct _OVERLAPPED
{
@ -477,6 +503,7 @@ typedef struct _WIN32_FIND_DATAA* LPWIN32_FIND_DATAA;
extern "C" {
DWORD WINAPI XInputGetState(DWORD dwUserIndex, XINPUT_STATE* pState);
int PASCAL closesocket(SOCKET s);
int PASCAL WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData);
SOCKET PASCAL socket(int af, int type, int protocol);
@ -628,5 +655,7 @@ LPVOID WINAPI CreateFiber(SIZE_T dwStackSize, LPFIBER_START_ROUTINE lpStartAddre
LPVOID WINAPI ConvertThreadToFiber(LPVOID lpParameter);
WINBASEAPI VOID WINAPI SwitchToFiber(LPVOID lpFiber);
WINBASEAPI VOID WINAPI DeleteFiber(PVOID lpFiber);
HRESULT WINAPI SetProcessDpiAwareness(PROCESS_DPI_AWARENESS value);
DECLSPEC_IMPORT BOOL WINAPI SetProcessDPIAware(VOID);
} // extern "C"

View File

@ -1339,49 +1339,44 @@ void GUIScene::reflect() {
}
};
LUMIX_SCENE(GUISceneImpl, "gui",
LUMIX_FUNC(GUIScene::getRectAt),
LUMIX_FUNC(GUIScene::isOver),
LUMIX_FUNC(GUIScene::getSystem),
LUMIX_CMP(RenderTarget, "gui_render_target", "GUI / Render taget"),
LUMIX_CMP(Text, "gui_text", "GUI / Text",
icon(ICON_FA_FONT),
LUMIX_PROP(Text, "Text", MultilineAttribute()),
LUMIX_PROP(TextFontPath, "Font", ResourceAttribute(FontResource::TYPE)),
LUMIX_PROP(TextFontSize, "Font Size"),
enum_property("Horizontal align", &GUIScene::getTextHAlign, &GUIScene::setTextHAlign, TextHAlignEnum()),
enum_property("Vertical align", &GUIScene::getTextVAlign, &GUIScene::setTextVAlign, TextVAlignEnum()),
LUMIX_PROP(TextColorRGBA, "Color", ColorAttribute())
),
LUMIX_CMP(InputField, "gui_input_field", "GUI / Input field", icon(ICON_FA_KEYBOARD)),
LUMIX_CMP(Canvas, "gui_canvas", "GUI / Canvas",
var_property("Is 3D", &GUIScene::getCanvas, &GUICanvas::is_3d),
var_property("Orient to camera", &GUIScene::getCanvas, &GUICanvas::orient_to_camera),
var_property("Virtual size", &GUIScene::getCanvas, &GUICanvas::virtual_size)
),
LUMIX_CMP(Button, "gui_button", "GUI / Button",
LUMIX_PROP(ButtonHoveredColorRGBA, "Hovered color", ColorAttribute()),
enum_property("Cursor", &GUIScene::getButtonHoveredCursor, &GUIScene::setButtonHoveredCursor, CursorEnum())
),
LUMIX_CMP(Image, "gui_image", "GUI / Image",
icon(ICON_FA_IMAGE),
property("Enabled", &GUIScene::isImageEnabled, &GUIScene::enableImage),
LUMIX_PROP(ImageColorRGBA, "Color", ColorAttribute()),
LUMIX_PROP(ImageSprite, "Sprite", ResourceAttribute(Sprite::TYPE))
),
LUMIX_CMP(Rect, "gui_rect", "GUI / Rect",
property("Enabled", &GUIScene::isRectEnabled, &GUIScene::enableRect),
LUMIX_PROP(RectClip, "Clip content"),
LUMIX_PROP(RectTopPoints, "Top Points"),
LUMIX_PROP(RectTopRelative, "Top Relative"),
LUMIX_PROP(RectRightPoints, "Right Points"),
LUMIX_PROP(RectRightRelative, "Right Relative"),
LUMIX_PROP(RectBottomPoints, "Bottom Points"),
LUMIX_PROP(RectBottomRelative, "Bottom Relative"),
LUMIX_PROP(RectLeftPoints, "Left Points"),
LUMIX_PROP(RectLeftRelative, "Left Relative")
)
);
LUMIX_SCENE(GUISceneImpl, "gui")
.LUMIX_FUNC(GUIScene::getRectAt)
.LUMIX_FUNC(GUIScene::isOver)
.LUMIX_FUNC(GUIScene::getSystem)
.LUMIX_CMP(RenderTarget, "gui_render_target", "GUI / Render taget")
.LUMIX_CMP(Text, "gui_text", "GUI / Text")
.icon(ICON_FA_FONT)
.LUMIX_PROP(Text, "Text").multilineAttribute()
.LUMIX_PROP(TextFontPath, "Font").resourceAttribute(FontResource::TYPE)
.LUMIX_PROP(TextFontSize, "Font Size")
.LUMIX_ENUM_PROP(TextHAlign, "Horizontal align").attribute<TextHAlignEnum>()
.LUMIX_ENUM_PROP(TextVAlign, "Vertical align").attribute<TextVAlignEnum>()
.LUMIX_PROP(TextColorRGBA, "Color").colorAttribute()
.LUMIX_CMP(InputField, "gui_input_field", "GUI / Input field").icon(ICON_FA_KEYBOARD)
.LUMIX_CMP(Canvas, "gui_canvas", "GUI / Canvas")
.var_prop<&GUIScene::getCanvas, &GUICanvas::is_3d>("Is 3D")
.var_prop<&GUIScene::getCanvas, &GUICanvas::orient_to_camera>("Orient to camera")
.var_prop<&GUIScene::getCanvas, &GUICanvas::virtual_size>("Virtual size")
.LUMIX_CMP(Button, "gui_button", "GUI / Button")
.LUMIX_PROP(ButtonHoveredColorRGBA, "Hovered color").colorAttribute()
.LUMIX_ENUM_PROP(ButtonHoveredCursor, "Cursor").attribute<CursorEnum>()
.LUMIX_CMP(Image, "gui_image", "GUI / Image")
.icon(ICON_FA_IMAGE)
.prop<&GUIScene::isImageEnabled, &GUIScene::enableImage>("Enabled")
.LUMIX_PROP(ImageColorRGBA, "Color").colorAttribute()
.LUMIX_PROP(ImageSprite, "Sprite").resourceAttribute(Sprite::TYPE)
.LUMIX_CMP(Rect, "gui_rect", "GUI / Rect")
.prop<&GUIScene::isRectEnabled, &GUIScene::enableRect>("Enabled")
.LUMIX_PROP(RectClip, "Clip content")
.LUMIX_PROP(RectTopPoints, "Top Points")
.LUMIX_PROP(RectTopRelative, "Top Relative")
.LUMIX_PROP(RectRightPoints, "Right Points")
.LUMIX_PROP(RectRightRelative, "Right Relative")
.LUMIX_PROP(RectBottomPoints, "Bottom Points")
.LUMIX_PROP(RectBottomRelative, "Bottom Relative")
.LUMIX_PROP(RectLeftPoints, "Left Points")
.LUMIX_PROP(RectLeftRelative, "Left Relative")
;
}
} // namespace Lumix

View File

@ -65,7 +65,7 @@ struct GUISystemImpl final : GUISystem
, m_sprite_manager(engine.getAllocator())
{
GUIScene::reflect();
LUMIX_FUNC(GUISystem::enableCursor);
LUMIX_GLOBAL_FUNC(GUISystem::enableCursor);
m_sprite_manager.create(Sprite::TYPE, m_engine.getResourceManager());
}

View File

@ -17,7 +17,6 @@
#include "engine/lua_wrapper.h"
#include "engine/os.h"
#include "engine/path.h"
#include "engine/reflection.h"
#include "engine/stream.h"
#include "engine/universe.h"
#include "lua_script/lua_script.h"

View File

@ -924,8 +924,8 @@ namespace Lumix
LuaWrapper::push(L, tmp);
}
void visit(const reflection::IArrayProperty& prop) override {}
void visit(const reflection::IBlobProperty& prop) override {}
void visit(const reflection::ArrayProperty& prop) override {}
void visit(const reflection::BlobProperty& prop) override {}
ComponentUID cmp;
const char* prop_name;
@ -979,8 +979,8 @@ namespace Lumix
prop.set(cmp, idx, val);
}
void visit(const reflection::IArrayProperty& prop) override {}
void visit(const reflection::IBlobProperty& prop) override {}
void visit(const reflection::ArrayProperty& prop) override {}
void visit(const reflection::BlobProperty& prop) override {}
ComponentUID cmp;
const char* prop_name;
@ -1044,8 +1044,7 @@ namespace Lumix
if (v.found) return 1;
// TODO put this directly in table, so we don't have to look it up here every time
const auto& functions = cmp->getFunctions();
for (auto* f : functions) {
for (auto* f : cmp->functions) {
if (equalStrings(v.prop_name, f->name)) {
lua_pushlightuserdata(L, (void*)f);
lua_pushcclosure(L, luaCmpMethodClosure, 1);
@ -1098,7 +1097,7 @@ namespace Lumix
lua_State* L = m_system.m_engine.getState();
LuaWrapper::DebugGuard guard(L);
reflection::SceneBase* scene = reflection::getFirstScene();
reflection::Scene* scene = reflection::getFirstScene();
while (scene) {
lua_newtable(L); // [ scene ]
lua_getglobal(L, "Lumix"); // [ scene, Lumix ]
@ -1112,9 +1111,10 @@ namespace Lumix
lua_pushcfunction(L, lua_new_scene); // [ scene, fn_new_scene ]
lua_setfield(L, -2, "new"); // [ scene ]
for (const reflection::FunctionBase* f : scene->getFunctions()) {
for (const reflection::FunctionBase* f : scene->functions) {
const char* c = f->decl_code;
while (*c != ':') ++c;
while (*c != ':' && *c) ++c;
ASSERT(*c == ':');
c += 2;
lua_pushlightuserdata(L, (void*)f); // [scene, f]
lua_pushcclosure(L, luaSceneMethodClosure, 1); // [scene, fn]
@ -2207,8 +2207,12 @@ namespace Lumix
}
struct LuaProperties : reflection::IDynamicProperties {
LuaProperties() { name = "lua_properties"; }
struct LuaProperties : reflection::DynamicProperties {
LuaProperties(IAllocator& allocator)
: DynamicProperties(allocator)
{
name = "lua_properties";
}
u32 getCount(ComponentUID cmp, int index) const override {
LuaScriptSceneImpl& scene = (LuaScriptSceneImpl&)*cmp.scene;
@ -2319,15 +2323,15 @@ namespace Lumix
{
m_script_manager.create(LuaScript::TYPE, engine.getResourceManager());
LUMIX_SCENE(LuaScriptSceneImpl, "lua_script",
LUMIX_CMP(Component, "lua_script", "Lua script",
array("scripts", &LuaScriptScene::getScriptCount, &LuaScriptScene::addScript, &LuaScriptScene::removeScript,
property("Enabled", &LuaScriptScene::isScriptEnabled, &LuaScriptScene::enableScript),
LUMIX_PROP(ScriptPath, "Path", ResourceAttribute(LuaScript::TYPE)),
LuaProperties()
)
)
);
LUMIX_SCENE(LuaScriptSceneImpl, "lua_script")
.LUMIX_CMP(Component, "lua_script", "Lua script")
.begin_array<&LuaScriptScene::getScriptCount, &LuaScriptScene::addScript, &LuaScriptScene::removeScript>("scripts")
.prop<&LuaScriptScene::isScriptEnabled, &LuaScriptScene::enableScript>("Enabled")
.LUMIX_PROP(ScriptPath, "Path").resourceAttribute(LuaScript::TYPE)
//LuaProperties()
.end_array()
// TODO refl
;
}
void LuaScriptSystemImpl::init() {

View File

@ -1534,33 +1534,32 @@ UniquePtr<NavigationScene> NavigationScene::create(Engine& engine, IPlugin& syst
return UniquePtr<NavigationSceneImpl>::create(allocator, engine, system, universe, allocator);
}
void NavigationScene::reflect() {
LUMIX_SCENE(NavigationSceneImpl, "navigation",
LUMIX_FUNC(NavigationScene::setGeneratorParams),
LUMIX_CMP(Zone, "navmesh_zone", "Navigation / Zone",
icon(ICON_FA_MAP_MARKED_ALT),
LUMIX_FUNC_EX(NavigationScene::debugDrawContours, "drawContours"),
LUMIX_FUNC_EX(NavigationScene::debugDrawNavmesh, "drawNavmesh"),
LUMIX_FUNC_EX(NavigationScene::debugDrawCompactHeightfield, "drawCompactHeightfield"),
LUMIX_FUNC_EX(NavigationScene::debugDrawHeightfield, "drawHeightfield"),
LUMIX_FUNC(NavigationScene::save),
LUMIX_FUNC(NavigationScene::load),
LUMIX_FUNC(NavigationScene::generateNavmesh),
var_property("Extents", &NavigationScene::getZone, &NavmeshZone::extents)
),
LUMIX_CMP(Agent, "navmesh_agent", "Navigation / Agent",
icon(ICON_FA_STREET_VIEW),
LUMIX_FUNC_EX(NavigationScene::setActorActive, "setActive"),
LUMIX_FUNC_EX(NavigationScene::navigate, "navigate"),
LUMIX_FUNC_EX(NavigationScene::cancelNavigation, "cancelNavigation"),
LUMIX_FUNC_EX(NavigationScene::getAgentSpeed, "getSpeed"),
LUMIX_FUNC_EX(NavigationScene::debugDrawPath, "drawPath"),
LUMIX_PROP(AgentRadius, "Radius", MinAttribute(0)),
LUMIX_PROP(AgentHeight, "Height", MinAttribute(0)),
property("Use root motion", &NavigationScene::useAgentRootMotion, &NavigationScene::setUseAgentRootMotion)
//property("Get root motion from animation", LUMIX_PROP_FULL(NavigationScene, isGettingRootMotionFromAnim, setIsGettingRootMotionFromAnim))
)
);
LUMIX_SCENE(NavigationSceneImpl, "navigation")
.LUMIX_FUNC(NavigationSceneImpl::setGeneratorParams)
.LUMIX_CMP(Zone, "navmesh_zone", "Navigation / Zone")
.icon(ICON_FA_STREET_VIEW)
.LUMIX_FUNC_EX(debugDrawContours, "drawContours")
.LUMIX_FUNC_EX(debugDrawNavmesh, "drawNavmesh")
.LUMIX_FUNC_EX(debugDrawCompactHeightfield, "drawCompactHeightfield")
.LUMIX_FUNC_EX(debugDrawHeightfield, "drawHeightfield")
.LUMIX_FUNC(save)
.LUMIX_FUNC(load)
.LUMIX_FUNC(generateNavmesh)
.var_prop<&NavigationScene::getZone, &NavmeshZone::extents>("Extents")
.LUMIX_CMP(Agent, "navmesh_agent", "Navigation / Agent")
.icon(ICON_FA_MAP_MARKED_ALT)
.LUMIX_FUNC_EX(setActorActive, "setActive")
.LUMIX_FUNC_EX(navigate, "navigate")
.LUMIX_FUNC_EX(cancelNavigation, "cancelNavigation")
.LUMIX_FUNC_EX(getAgentSpeed, "getSpeed")
.LUMIX_FUNC_EX(debugDrawPath, "drawPath")
.LUMIX_PROP(AgentRadius, "Radius").minAttribute(0)
.LUMIX_PROP(AgentHeight, "Height").minAttribute(0)
.prop<&NavigationScene::useAgentRootMotion, &NavigationScene::setUseAgentRootMotion>("Use root motion");
}
} // namespace Lumix

View File

@ -3,7 +3,6 @@
#include "engine/engine.h"
#include "engine/lumix.h"
#include "engine/math.h"
#include "engine/reflection.h"
#include "engine/universe.h"
#include "navigation/navigation_scene.h"
#include "renderer/material.h"

View File

@ -19,7 +19,6 @@
#include "engine/log.h"
#include "engine/math.h"
#include "engine/path.h"
#include "engine/reflection.h"
#include "engine/universe.h"
#include "physics/physics_geometry.h"
#include "physics/physics_scene.h"

View File

@ -4532,125 +4532,106 @@ void PhysicsScene::reflect() {
}
};
// "temporary" hack to fix crash at startup on linux
// last good commmit around eb0e5c9b6fc7ce3de197c5c0b2b30e9f8c9653eb
#ifdef _WIN32
#define VEHICLE_CMP \
, \
LUMIX_FUNC_EX(PhysicsScene::setVehicleAccel, "setAccel"), \
LUMIX_FUNC_EX(PhysicsScene::setVehicleSteer, "setSteer"), \
LUMIX_PROP(VehicleMass, "Mass", MinAttribute(0)), \
LUMIX_PROP(VehicleCenterOfMass, "Center of mass"), \
LUMIX_PROP(VehicleMOIMultiplier, "MOI multiplier"), \
LUMIX_PROP(VehicleChassis, "Chassis", ResourceAttribute(PhysicsGeometry::TYPE)), \
LUMIX_PROP(VehicleChassisLayer, "Chassis layer", LayerEnum()), \
LUMIX_PROP(VehicleWheelsLayer, "Wheels layer", LayerEnum())
#else
#define VEHICLE_CMP
#endif
LUMIX_SCENE(PhysicsSceneImpl, "physics",
LUMIX_FUNC(PhysicsSceneImpl::raycast),
//function(LUMIX_FUNC(PhysicsScene::raycastEx))
LUMIX_CMP(Ragdoll, "ragdoll", "Physics / Ragdoll",
icon(ICON_FA_MALE),
LUMIX_FUNC(PhysicsScene::setRagdollKinematic),
blob_property("data", &PhysicsScene::getRagdollData, &PhysicsScene::setRagdollData),
LUMIX_PROP(RagdollLayer, "Layer", LayerEnum())
),
LUMIX_CMP(D6Joint, "d6_joint", "Physics / Joint / D6",
LUMIX_PROP(JointConnectedBody, "Connected body"),
LUMIX_PROP(JointAxisPosition, "Axis position"),
LUMIX_PROP(JointAxisDirection, "Axis direction"),
enum_property("X motion", &PhysicsScene::getD6JointXMotion, &PhysicsScene::setD6JointXMotion, D6MotionEnum()),
enum_property("Y motion", &PhysicsScene::getD6JointYMotion, &PhysicsScene::setD6JointYMotion, D6MotionEnum()),
enum_property("Z motion", &PhysicsScene::getD6JointZMotion, &PhysicsScene::setD6JointZMotion, D6MotionEnum()),
enum_property("Swing 1", &PhysicsScene::getD6JointSwing1Motion, &PhysicsScene::setD6JointSwing1Motion, D6MotionEnum()),
enum_property("Swing 2", &PhysicsScene::getD6JointSwing2Motion, &PhysicsScene::setD6JointSwing2Motion, D6MotionEnum()),
enum_property("Twist", &PhysicsScene::getD6JointTwistMotion, &PhysicsScene::setD6JointTwistMotion, D6MotionEnum()),
LUMIX_PROP(D6JointLinearLimit, "Linear limit", MinAttribute(0)),
LUMIX_PROP(D6JointSwingLimit, "Swing limit", RadiansAttribute()),
LUMIX_PROP(D6JointTwistLimit, "Twist limit", RadiansAttribute()),
LUMIX_PROP(D6JointDamping, "Damping"),
LUMIX_PROP(D6JointStiffness, "Stiffness"),
LUMIX_PROP(D6JointRestitution, "Restitution")
),
LUMIX_CMP(SphericalJoint, "spherical_joint", "Physics / Joint / Spherical",
LUMIX_PROP(JointConnectedBody, "Connected body"),
LUMIX_PROP(JointAxisPosition, "Axis position"),
LUMIX_PROP(JointAxisDirection, "Axis direction"),
LUMIX_PROP(SphericalJointUseLimit, "Use limit"),
LUMIX_PROP(SphericalJointLimit, "Limit", RadiansAttribute())
),
LUMIX_CMP(DistanceJoint, "distance_joint", "Physics / Joint / Distance",
LUMIX_PROP(JointConnectedBody, "Connected body"),
LUMIX_PROP(JointAxisPosition, "Axis position"),
LUMIX_PROP(DistanceJointDamping, "Damping", MinAttribute(0)),
LUMIX_PROP(DistanceJointStiffness, "Stiffness", MinAttribute(0)),
LUMIX_PROP(DistanceJointTolerance, "Tolerance", MinAttribute(0)),
LUMIX_PROP(DistanceJointLimits, "Limits")
),
LUMIX_CMP(HingeJoint, "hinge_joint", "Physics / Joint / Hinge",
LUMIX_PROP(JointConnectedBody, "Connected body"),
LUMIX_PROP(JointAxisPosition, "Axis position"),
LUMIX_PROP(JointAxisDirection, "Axis direction"),
LUMIX_PROP(HingeJointDamping, "Damping", MinAttribute(0)),
LUMIX_PROP(HingeJointStiffness, "Stiffness", MinAttribute(0)),
LUMIX_PROP(HingeJointUseLimit, "Use limit"),
LUMIX_PROP(HingeJointLimit, "Limit", RadiansAttribute())
),
LUMIX_CMP(Controller, "physical_controller", "Physics / Controller",
LUMIX_FUNC_EX(PhysicsScene::moveController, "move"),
LUMIX_FUNC_EX(PhysicsScene::isControllerCollisionDown, "isCollisionDown"),
LUMIX_PROP(ControllerRadius, "Radius"),
LUMIX_PROP(ControllerHeight, "Height"),
LUMIX_PROP(ControllerLayer, "Layer", LayerEnum()),
LUMIX_PROP(ControllerUseRootMotion, "Use root motion"),
LUMIX_PROP(ControllerCustomGravity, "Use custom gravity"),
LUMIX_PROP(ControllerCustomGravityAcceleration, "Custom gravity acceleration")
),
LUMIX_CMP(RigidActor, "rigid_actor", "Physics / Rigid actor",
icon(ICON_FA_VOLLEYBALL_BALL),
LUMIX_FUNC_EX(PhysicsScene::putToSleep, "putToSleep"),
LUMIX_FUNC_EX(PhysicsScene::getActorSpeed, "getSpeed"),
LUMIX_FUNC_EX(PhysicsScene::getActorVelocity, "getVelocity"),
LUMIX_FUNC_EX(PhysicsScene::applyForceToActor, "applyForce"),
LUMIX_FUNC_EX(PhysicsScene::applyForceToActor, "applyImpulse"),
LUMIX_FUNC_EX(PhysicsScene::addForceAtPos, "addForceAtPos"),
LUMIX_PROP(ActorLayer, "Layer", LayerEnum()),
enum_property("Dynamic", &PhysicsSceneImpl::getDynamicType, &PhysicsSceneImpl::setDynamicType, DynamicTypeEnum()),
LUMIX_PROP(IsTrigger, "Trigger"),
array("Box geometry", &PhysicsScene::getBoxGeometryCount, &PhysicsScene::addBoxGeometry, &PhysicsScene::removeBoxGeometry,
LUMIX_PROP(BoxGeomHalfExtents, "Size"),
LUMIX_PROP(BoxGeomOffsetPosition, "Position offset"),
LUMIX_PROP(BoxGeomOffsetRotation, "Rotation offset", RadiansAttribute())),
array("Sphere geometry", &PhysicsScene::getSphereGeometryCount, &PhysicsScene::addSphereGeometry, &PhysicsScene::removeSphereGeometry,
LUMIX_PROP(SphereGeomRadius, "Radius", MinAttribute(0)),
LUMIX_PROP(SphereGeomOffsetPosition, "Position offset")),
LUMIX_PROP(MeshGeomPath, "Mesh", ResourceAttribute(PhysicsGeometry::TYPE))
),
LUMIX_CMP(Vehicle, "vehicle", "Physics / Vehicle",
icon(ICON_FA_CAR_ALT)
VEHICLE_CMP
),
LUMIX_CMP(Wheel, "wheel", "Physics / Wheel",
LUMIX_PROP(WheelRadius, "Radius", MinAttribute(0)),
LUMIX_PROP(WheelWidth, "Width", MinAttribute(0)),
LUMIX_PROP(WheelMass, "Mass", MinAttribute(0)),
LUMIX_PROP(WheelMOI, "MOI", MinAttribute(0)),
LUMIX_PROP(WheelSpringMaxCompression, "Max compression", MinAttribute(0)),
LUMIX_PROP(WheelSpringMaxDroop, "Max droop", MinAttribute(0)),
LUMIX_PROP(WheelSpringStrength, "Spring strength", MinAttribute(0)),
LUMIX_PROP(WheelSpringDamperRate, "Spring damper rate", MinAttribute(0)),
enum_property("Slot", &PhysicsSceneImpl::getWheelSlot, &PhysicsSceneImpl::setWheelSlot, WheelSlotEnum())
),
LUMIX_CMP(Heightfield, "physical_heightfield", "Physics / Heightfield",
LUMIX_PROP(HeightfieldLayer, "Layer", LayerEnum()),
LUMIX_PROP(HeightmapSource, "Heightmap", ResourceAttribute(Texture::TYPE)),
LUMIX_PROP(HeightmapYScale, "Y scale", MinAttribute(0)),
LUMIX_PROP(HeightmapXZScale, "XZ scale", MinAttribute(0))
)
);
LUMIX_SCENE(PhysicsSceneImpl, "physics")
.LUMIX_FUNC(PhysicsSceneImpl::raycast)
.LUMIX_CMP(Ragdoll, "ragdoll", "Physics / Ragdoll")
.icon(ICON_FA_MALE)
.LUMIX_FUNC(PhysicsScene::setRagdollKinematic)
.blob_property<&PhysicsScene::getRagdollData, &PhysicsScene::setRagdollData>("data")
.LUMIX_ENUM_PROP(RagdollLayer, "Layer").attribute<LayerEnum>()
.LUMIX_CMP(D6Joint, "d6_joint", "Physics / Joint / D6")
.LUMIX_PROP(JointConnectedBody, "Connected body")
.LUMIX_PROP(JointAxisPosition, "Axis position")
.LUMIX_PROP(JointAxisDirection, "Axis direction")
.LUMIX_ENUM_PROP(D6JointXMotion, "X motion").attribute<D6MotionEnum>()
.LUMIX_ENUM_PROP(D6JointYMotion, "Y motion").attribute<D6MotionEnum>()
.LUMIX_ENUM_PROP(D6JointZMotion, "Z motion").attribute<D6MotionEnum>()
.LUMIX_ENUM_PROP(D6JointSwing1Motion, "Swing 1").attribute<D6MotionEnum>()
.LUMIX_ENUM_PROP(D6JointSwing2Motion, "Swing 2").attribute<D6MotionEnum>()
.LUMIX_ENUM_PROP(D6JointTwistMotion, "Twist").attribute<D6MotionEnum>()
.LUMIX_PROP(D6JointLinearLimit, "Linear limit").minAttribute(0)
.LUMIX_PROP(D6JointSwingLimit, "Swing limit").radiansAttribute()
.LUMIX_PROP(D6JointTwistLimit, "Twist limit").radiansAttribute()
.LUMIX_PROP(D6JointDamping, "Damping")
.LUMIX_PROP(D6JointStiffness, "Stiffness")
.LUMIX_PROP(D6JointRestitution, "Restitution")
.LUMIX_CMP(SphericalJoint, "spherical_joint", "Physics / Joint / Spherical")
.LUMIX_PROP(JointConnectedBody, "Connected body")
.LUMIX_PROP(JointAxisPosition, "Axis position")
.LUMIX_PROP(JointAxisDirection, "Axis direction")
.LUMIX_PROP(SphericalJointUseLimit, "Use limit")
.LUMIX_PROP(SphericalJointLimit, "Limit").radiansAttribute()
.LUMIX_CMP(DistanceJoint, "distance_joint", "Physics / Joint / Distance")
.LUMIX_PROP(JointConnectedBody, "Connected body")
.LUMIX_PROP(JointAxisPosition, "Axis position")
.LUMIX_PROP(DistanceJointDamping, "Damping").minAttribute(0)
.LUMIX_PROP(DistanceJointStiffness, "Stiffness").minAttribute(0)
.LUMIX_PROP(DistanceJointTolerance, "Tolerance").minAttribute(0)
.LUMIX_PROP(DistanceJointLimits, "Limits")
.LUMIX_CMP(HingeJoint, "hinge_joint", "Physics / Joint / Hinge")
.LUMIX_PROP(JointConnectedBody, "Connected body")
.LUMIX_PROP(JointAxisPosition, "Axis position")
.LUMIX_PROP(JointAxisDirection, "Axis direction")
.LUMIX_PROP(HingeJointDamping, "Damping").minAttribute(0)
.LUMIX_PROP(HingeJointStiffness, "Stiffness").minAttribute(0)
.LUMIX_PROP(HingeJointUseLimit, "Use limit")
.LUMIX_PROP(HingeJointLimit, "Limit").radiansAttribute()
.LUMIX_CMP(Controller, "physical_controller", "Physics / Controller")
.LUMIX_FUNC_EX(PhysicsScene::moveController, "move")
.LUMIX_FUNC_EX(PhysicsScene::isControllerCollisionDown, "isCollisionDown")
.LUMIX_PROP(ControllerRadius, "Radius")
.LUMIX_PROP(ControllerHeight, "Height")
.LUMIX_ENUM_PROP(ControllerLayer, "Layer").attribute<LayerEnum>()
.LUMIX_PROP(ControllerUseRootMotion, "Use root motion")
.LUMIX_PROP(ControllerCustomGravity, "Use custom gravity")
.LUMIX_PROP(ControllerCustomGravityAcceleration, "Custom gravity acceleration")
.LUMIX_CMP(RigidActor, "rigid_actor", "Physics / Rigid actor")
.icon(ICON_FA_VOLLEYBALL_BALL)
.LUMIX_FUNC_EX(PhysicsScene::putToSleep, "putToSleep")
.LUMIX_FUNC_EX(PhysicsScene::getActorSpeed, "getSpeed")
.LUMIX_FUNC_EX(PhysicsScene::getActorVelocity, "getVelocity")
.LUMIX_FUNC_EX(PhysicsScene::applyForceToActor, "applyForce")
.LUMIX_FUNC_EX(PhysicsScene::applyForceToActor, "applyImpulse")
.LUMIX_FUNC_EX(PhysicsScene::addForceAtPos, "addForceAtPos")
.LUMIX_ENUM_PROP(ActorLayer, "Layer").attribute<LayerEnum>()
.LUMIX_ENUM_PROP(DynamicType, "Dynamic").attribute<DynamicTypeEnum>()
.LUMIX_PROP(IsTrigger, "Trigger")
.begin_array<&PhysicsScene::getBoxGeometryCount, &PhysicsScene::addBoxGeometry, &PhysicsScene::removeBoxGeometry>("Box geometry")
.LUMIX_PROP(BoxGeomHalfExtents, "Size")
.LUMIX_PROP(BoxGeomOffsetPosition, "Position offset")
.LUMIX_PROP(BoxGeomOffsetRotation, "Rotation offset").radiansAttribute()
.end_array()
.begin_array<&PhysicsScene::getSphereGeometryCount, &PhysicsScene::addSphereGeometry, &PhysicsScene::removeSphereGeometry>("Sphere geometry")
.LUMIX_PROP(SphereGeomRadius, "Radius").minAttribute(0)
.LUMIX_PROP(SphereGeomOffsetPosition, "Position offset")
.end_array()
.LUMIX_PROP(MeshGeomPath, "Mesh").resourceAttribute(PhysicsGeometry::TYPE)
.LUMIX_CMP(Vehicle, "vehicle", "Physics / Vehicle")
.icon(ICON_FA_CAR_ALT)
.LUMIX_FUNC_EX(PhysicsScene::setVehicleAccel, "setAccel")
.LUMIX_FUNC_EX(PhysicsScene::setVehicleSteer, "setSteer")
.LUMIX_PROP(VehicleMass, "Mass").minAttribute(0)
.LUMIX_PROP(VehicleCenterOfMass, "Center of mass")
.LUMIX_PROP(VehicleMOIMultiplier, "MOI multiplier")
.LUMIX_PROP(VehicleChassis, "Chassis").resourceAttribute(PhysicsGeometry::TYPE)
.LUMIX_ENUM_PROP(VehicleChassisLayer, "Chassis layer").attribute<LayerEnum>()
.LUMIX_ENUM_PROP(VehicleWheelsLayer, "Wheels layer").attribute<LayerEnum>()
.LUMIX_CMP(Wheel, "wheel", "Physics / Wheel")
.LUMIX_PROP(WheelRadius, "Radius").minAttribute(0)
.LUMIX_PROP(WheelWidth, "Width").minAttribute(0)
.LUMIX_PROP(WheelMass, "Mass").minAttribute(0)
.LUMIX_PROP(WheelMOI, "MOI").minAttribute(0)
.LUMIX_PROP(WheelSpringMaxCompression, "Max compression").minAttribute(0)
.LUMIX_PROP(WheelSpringMaxDroop, "Max droop").minAttribute(0)
.LUMIX_PROP(WheelSpringStrength, "Spring strength").minAttribute(0)
.LUMIX_PROP(WheelSpringDamperRate, "Spring damper rate").minAttribute(0)
.LUMIX_ENUM_PROP(WheelSlot, "Slot").attribute<WheelSlotEnum>()
.LUMIX_CMP(Heightfield, "physical_heightfield", "Physics / Heightfield")
.LUMIX_ENUM_PROP(HeightfieldLayer, "Layer").attribute<LayerEnum>()
.LUMIX_PROP(HeightmapSource, "Heightmap").resourceAttribute(Texture::TYPE)
.LUMIX_PROP(HeightmapYScale, "Y scale").minAttribute(0)
.LUMIX_PROP(HeightmapXZScale, "XZ scale").minAttribute(0)
;
}
void PhysicsSceneImpl::RigidActor::onStateChanged(Resource::State, Resource::State new_state, Resource&)

View File

@ -13,7 +13,6 @@
#include "engine/engine.h"
#include "engine/log.h"
#include "engine/lua_wrapper.h"
#include "engine/reflection.h"
#include "engine/resource_manager.h"
#include "engine/universe.h"
#include "physics/physics_geometry.h"

View File

@ -5,7 +5,6 @@
#include "engine/geometry.h"
#include "engine/math.h"
#include "engine/os.h"
#include "engine/reflection.h"
#include "engine/resource_manager.h"
#include "engine/universe.h"
#include "renderer/model.h"

View File

@ -9,7 +9,6 @@
#include "engine/engine.h"
#include "engine/file_system.h"
#include "engine/log.h"
#include "engine/reflection.h"
#include "engine/string.h"
#include "engine/universe.h"
#include "renderer/material.h"

View File

@ -26,7 +26,6 @@
#include "engine/prefab.h"
#include "engine/profiler.h"
#include "engine/queue.h"
#include "engine/reflection.h"
#include "engine/resource_manager.h"
#include "engine/universe.h"
#include "fbx_importer.h"

View File

@ -17,7 +17,6 @@
#include "engine/path.h"
#include "engine/prefab.h"
#include "engine/profiler.h"
#include "engine/reflection.h"
#include "engine/resource_manager.h"
#include "engine/string.h"
#include "engine/universe.h"

View File

@ -15,7 +15,6 @@
#include "engine/path.h"
#include "engine/prefab.h"
#include "engine/profiler.h"
#include "engine/reflection.h"
#include "engine/resource_manager.h"
#include "engine/universe.h"
#include "physics/physics_scene.h"

View File

@ -7,7 +7,6 @@
#include "engine/log.h"
#include "engine/math.h"
#include "engine/profiler.h"
#include "engine/reflection.h"
#include "engine/resource_manager.h"
#include "engine/simd.h"
#include "engine/stream.h"

View File

@ -3694,6 +3694,7 @@ struct PipelineImpl final : Pipeline
if (!iter.value().enabled) continue;
const Model* model = mi[e.index].model;
if (!model) continue;
if (!model->isReady()) continue;
for (i32 i = 0; i < model->getMeshCount(); ++i) {

View File

@ -2781,97 +2781,85 @@ void RenderScene::reflect() {
}
};
LUMIX_SCENE(RenderSceneImpl, "renderer",
LUMIX_FUNC(RenderScene::setGlobalLODMultiplier),
LUMIX_FUNC(RenderScene::getGlobalLODMultiplier),
LUMIX_FUNC(RenderScene::addDebugCross),
LUMIX_FUNC(RenderScene::addDebugLine),
LUMIX_FUNC(RenderScene::addDebugTriangle),
LUMIX_CMP(BoneAttachment, "bone_attachment", "Render / Bone attachment",
icon(ICON_FA_BONE),
LUMIX_PROP(BoneAttachmentParent, "Parent"),
LUMIX_PROP(BoneAttachmentPosition, "Relative position"),
LUMIX_PROP(BoneAttachmentRotation, "Relative rotation", RadiansAttribute()),
LUMIX_PROP(BoneAttachmentBone, "Bone", BoneEnum())
),
LUMIX_CMP(Fur, "fur", "Render / Fur",
var_property("Layers", &RenderScene::getFur, &FurComponent::layers),
var_property("Scale", &RenderScene::getFur, &FurComponent::scale),
var_property("Gravity", &RenderScene::getFur, &FurComponent::gravity),
var_property("Enabled", &RenderScene::getFur, &FurComponent::enabled)
),
LUMIX_CMP(EnvironmentProbe, "environment_probe", "Render / Environment probe",
property("Enabled", &RenderScene::isEnvironmentProbeEnabled, &RenderScene::enableEnvironmentProbe),
var_property("Inner range", &RenderScene::getEnvironmentProbe, &EnvironmentProbe::inner_range),
var_property("Outer range", &RenderScene::getEnvironmentProbe, &EnvironmentProbe::outer_range)
),
LUMIX_CMP(ReflectionProbe, "reflection_probe", "Render / Reflection probe",
property("Enabled", &RenderScene::isReflectionProbeEnabled, &RenderScene::enableReflectionProbe),
var_property("size", &RenderScene::getReflectionProbe, &ReflectionProbe::size),
var_property("half_extents", &RenderScene::getReflectionProbe, &ReflectionProbe::half_extents)
),
LUMIX_CMP(ParticleEmitter, "particle_emitter", "Render / Particle emitter",
LUMIX_PROP(ParticleEmitterRate, "Emit rate"),
LUMIX_PROP(ParticleEmitterPath, "Source", ResourceAttribute(ParticleEmitterResource::TYPE))
),
LUMIX_CMP(Camera, "camera", "Render / Camera",
icon(ICON_FA_CAMERA),
var_property("FOV", &RenderScene::getCamera, &Camera::fov, RadiansAttribute()),
var_property("Near", &RenderScene::getCamera, &Camera::near, MinAttribute(0)),
var_property("Far", &RenderScene::getCamera, &Camera::far, MinAttribute(0)),
var_property("Orthographic", &RenderScene::getCamera, &Camera::is_ortho),
var_property("Orthographic size", &RenderScene::getCamera, &Camera::ortho_size, MinAttribute(0))
),
LUMIX_CMP(ModelInstance, "model_instance", "Render / Mesh",
LUMIX_FUNC_EX(RenderScene::getModelInstanceModel, "getModel"),
property("Enabled", &RenderScene::isModelInstanceEnabled, &RenderScene::enableModelInstance),
property("Material", &RenderScene::getModelInstanceMaterialOverride,&RenderScene::setModelInstanceMaterialOverride, NoUIAttribute()),
LUMIX_PROP(ModelInstancePath, "Source", ResourceAttribute(Model::TYPE))
),
LUMIX_CMP(Environment, "environment", "Render / Environment",
icon(ICON_FA_GLOBE),
var_property("Color", &RenderScene::getEnvironment, &Environment::light_color, ColorAttribute()),
var_property("Intensity", &RenderScene::getEnvironment, &Environment::direct_intensity, MinAttribute(0)),
var_property("Indirect intensity", &RenderScene::getEnvironment, &Environment::indirect_intensity, MinAttribute(0)),
LUMIX_PROP(ShadowmapCascades, "Shadow cascades"),
LUMIX_PROP(EnvironmentCastShadows, "Cast shadows")
),
LUMIX_CMP(PointLight, "point_light", "Render / Point light",
icon(ICON_FA_LIGHTBULB),
LUMIX_PROP(PointLightCastShadows, "Cast shadows"),
LUMIX_PROP(PointLightDynamic, "Dynamic"),
var_property("Intensity", &RenderScene::getPointLight, &PointLight::intensity, MinAttribute(0)),
var_property("FOV", &RenderScene::getPointLight, &PointLight::fov, ClampAttribute(0, 360), RadiansAttribute()),
var_property("Attenuation", &RenderScene::getPointLight, &PointLight::attenuation_param, ClampAttribute(0, 100)),
var_property("Color", &RenderScene::getPointLight, &PointLight::color, ColorAttribute()),
LUMIX_PROP(LightRange, "Range", MinAttribute(0))
),
LUMIX_CMP(Decal, "decal", "Render / Decal",
LUMIX_PROP(DecalMaterialPath, "Material", ResourceAttribute(Material::TYPE)),
LUMIX_PROP(DecalHalfExtents, "Half extents", MinAttribute(0)),
var_property("UV scale", &RenderScene::getDecal, &Decal::uv_scale, MinAttribute(0))
),
LUMIX_CMP(CurveDecal, "curve_decal", "Render / Curve decal",
LUMIX_PROP(CurveDecalMaterialPath, "Material", ResourceAttribute(Material::TYPE)),
LUMIX_PROP(CurveDecalHalfExtents, "Half extents", MinAttribute(0)),
LUMIX_PROP(CurveDecalUVScale, "UV scale", MinAttribute(0)),
LUMIX_PROP(CurveDecalBezierP0, "Bezier P0", NoUIAttribute()),
LUMIX_PROP(CurveDecalBezierP2, "Bezier P2", NoUIAttribute())
),
LUMIX_CMP(Terrain, "terrain", "Render / Terrain",
LUMIX_FUNC(RenderScene::getTerrainNormalAt),
LUMIX_FUNC(RenderScene::getTerrainHeightAt),
LUMIX_PROP(TerrainMaterialPath, "Material", ResourceAttribute(Material::TYPE)),
LUMIX_PROP(TerrainXZScale, "XZ scale", MinAttribute(0)),
LUMIX_PROP(TerrainYScale, "Height scale", MinAttribute(0)),
array("grass", &RenderScene::getGrassCount, &RenderScene::addGrass, &RenderScene::removeGrass,
LUMIX_PROP(GrassPath, "Mesh", ResourceAttribute(Model::TYPE)),
LUMIX_PROP(GrassDistance, "Distance", MinAttribute(1)),
LUMIX_PROP(GrassSpacing, "Spacing"),
LUMIX_PROP(GrassRotationMode, "Mode", RotationModeEnum())
)
)
);
LUMIX_SCENE(RenderSceneImpl, "renderer")
.LUMIX_FUNC(RenderSceneImpl::setGlobalLODMultiplier)
.LUMIX_FUNC(RenderSceneImpl::getGlobalLODMultiplier)
.LUMIX_FUNC(RenderSceneImpl::addDebugCross)
.LUMIX_FUNC(RenderSceneImpl::addDebugLine)
.LUMIX_FUNC(RenderSceneImpl::addDebugTriangle)
.LUMIX_CMP(BoneAttachment, "bone_attachment", "Render / Bone attachment")
.icon(ICON_FA_BONE)
.LUMIX_PROP(BoneAttachmentParent, "Parent")
.LUMIX_PROP(BoneAttachmentPosition, "Relative position")
.LUMIX_PROP(BoneAttachmentRotation, "Relative rotation").radiansAttribute()
.LUMIX_PROP(BoneAttachmentBone, "Bone").attribute<BoneEnum>()
.LUMIX_CMP(Fur, "fur", "Render / Fur")
.var_prop<&RenderScene::getFur, &FurComponent::layers>("Layers")
.var_prop<&RenderScene::getFur, &FurComponent::scale>("Scale")
.var_prop<&RenderScene::getFur, &FurComponent::gravity>("Gravity")
.var_prop<&RenderScene::getFur, &FurComponent::enabled>("Enabled")
.LUMIX_CMP(EnvironmentProbe, "environment_probe", "Render / Environment probe")
.prop<&RenderScene::isEnvironmentProbeEnabled, &RenderScene::enableEnvironmentProbe>("Enabled")
.var_prop<&RenderScene::getEnvironmentProbe, &EnvironmentProbe::inner_range>("Inner range")
.var_prop<&RenderScene::getEnvironmentProbe, &EnvironmentProbe::outer_range>("Outer range")
.LUMIX_CMP(ReflectionProbe, "reflection_probe", "Render / Reflection probe")
.prop<&RenderScene::isReflectionProbeEnabled, &RenderScene::enableReflectionProbe>("Enabled")
.var_prop<&RenderScene::getReflectionProbe, &ReflectionProbe::size>("size")
.var_prop<&RenderScene::getReflectionProbe, &ReflectionProbe::half_extents>("half_extents")
.LUMIX_CMP(ParticleEmitter, "particle_emitter", "Render / Particle emitter")
.LUMIX_PROP(ParticleEmitterRate, "Emit rate")
.LUMIX_PROP(ParticleEmitterPath, "Source").resourceAttribute(ParticleEmitterResource::TYPE)
.LUMIX_CMP(Camera, "camera", "Render / Camera")
.icon(ICON_FA_CAMERA)
.var_prop<&RenderScene::getCamera, &Camera::fov>("FOV").radiansAttribute()
.var_prop<&RenderScene::getCamera, &Camera::near>("Near").minAttribute(0)
.var_prop<&RenderScene::getCamera, &Camera::far>("Far").minAttribute(0)
.var_prop<&RenderScene::getCamera, &Camera::is_ortho>("Orthographic")
.var_prop<&RenderScene::getCamera, &Camera::ortho_size>("Orthographic size").minAttribute(0)
.LUMIX_CMP(ModelInstance, "model_instance", "Render / Mesh")
.LUMIX_FUNC_EX(RenderScene::getModelInstanceModel, "getModel")
.prop<&RenderScene::isModelInstanceEnabled, &RenderScene::enableModelInstance>("Enabled")
.prop<&RenderScene::getModelInstanceMaterialOverride,&RenderScene::setModelInstanceMaterialOverride>("Material").noUIAttribute()
.LUMIX_PROP(ModelInstancePath, "Source").resourceAttribute(Model::TYPE)
.LUMIX_CMP(Environment, "environment", "Render / Environment")
.icon(ICON_FA_GLOBE)
.var_prop<&RenderScene::getEnvironment, &Environment::light_color>("Color").colorAttribute()
.var_prop<&RenderScene::getEnvironment, &Environment::direct_intensity>("Intensity").minAttribute(0)
.var_prop<&RenderScene::getEnvironment, &Environment::indirect_intensity>("Indirect intensity").minAttribute(0)
.LUMIX_PROP(ShadowmapCascades, "Shadow cascades")
.LUMIX_PROP(EnvironmentCastShadows, "Cast shadows")
.LUMIX_CMP(PointLight, "point_light", "Render / Point light")
.icon(ICON_FA_LIGHTBULB)
.LUMIX_PROP(PointLightCastShadows, "Cast shadows")
.LUMIX_PROP(PointLightDynamic, "Dynamic")
.var_prop<&RenderScene::getPointLight, &PointLight::intensity>("Intensity").minAttribute(0)
.var_prop<&RenderScene::getPointLight, &PointLight::fov>("FOV").clampAttribute(0, 360).radiansAttribute()
.var_prop<&RenderScene::getPointLight, &PointLight::attenuation_param>("Attenuation").clampAttribute(0, 100)
.var_prop<&RenderScene::getPointLight, &PointLight::color>("Color").colorAttribute()
.LUMIX_PROP(LightRange, "Range").minAttribute(0)
.LUMIX_CMP(Decal, "decal", "Render / Decal")
.LUMIX_PROP(DecalMaterialPath, "Material").resourceAttribute(Material::TYPE)
.LUMIX_PROP(DecalHalfExtents, "Half extents").minAttribute(0)
.var_prop<&RenderScene::getDecal, &Decal::uv_scale>("UV scale").minAttribute(0)
.LUMIX_CMP(CurveDecal, "curve_decal", "Render / Curve decal")
.LUMIX_PROP(CurveDecalMaterialPath, "Material").resourceAttribute(Material::TYPE)
.LUMIX_PROP(CurveDecalHalfExtents, "Half extents").minAttribute(0)
.LUMIX_PROP(CurveDecalUVScale, "UV scale").minAttribute(0)
.LUMIX_PROP(CurveDecalBezierP0, "Bezier P0").noUIAttribute()
.LUMIX_PROP(CurveDecalBezierP2, "Bezier P2").noUIAttribute()
.LUMIX_CMP(Terrain, "terrain", "Render / Terrain")
.LUMIX_FUNC(RenderScene::getTerrainNormalAt)
.LUMIX_FUNC(RenderScene::getTerrainHeightAt)
.LUMIX_PROP(TerrainMaterialPath, "Material").resourceAttribute(Material::TYPE)
.LUMIX_PROP(TerrainXZScale, "XZ scale").minAttribute(0)
.LUMIX_PROP(TerrainYScale, "Height scale").minAttribute(0)
.begin_array<&RenderScene::getGrassCount, &RenderScene::addGrass, &RenderScene::removeGrass>("grass")
.LUMIX_PROP(GrassPath, "Mesh").resourceAttribute(Model::TYPE)
.LUMIX_PROP(GrassDistance, "Distance").minAttribute(1)
.LUMIX_PROP(GrassSpacing, "Spacing")
.LUMIX_PROP(GrassRotationMode, "Mode").attribute<RotationModeEnum>()
.end_array()
;
}
RenderSceneImpl::RenderSceneImpl(Renderer& renderer,

View File

@ -357,9 +357,9 @@ struct RendererImpl final : Renderer
{
RenderScene::reflect();
LUMIX_FUNC(Model::getBoneCount);
LUMIX_FUNC(Model::getBoneName);
LUMIX_FUNC(Model::getBoneParent);
LUMIX_GLOBAL_FUNC(Model::getBoneCount);
LUMIX_GLOBAL_FUNC(Model::getBoneName);
LUMIX_GLOBAL_FUNC(Model::getBoneParent);
m_shader_defines.reserve(32);

View File

@ -6,7 +6,6 @@
#include "engine/log.h"
#include "engine/math.h"
#include "engine/profiler.h"
#include "engine/reflection.h"
#include "engine/resource_manager.h"
#include "engine/stream.h"
#include "renderer/material.h"

View File

@ -1,16 +1,13 @@
#define NOGDI
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <Winuser.h>
#include <ShellScalingAPI.h>
#include "engine/os.h"
#include "engine/win/simple_win.h"
#include "editor/studio_app.h"
int main(int argc, char* argv[])
{
SetProcessDPIAware();
HMODULE shcore = LoadLibrary("shcore.dll");
void* shcore = Lumix::os::loadLibrary("shcore.dll");
if (shcore) {
auto setter = (decltype(&SetProcessDpiAwareness))GetProcAddress(shcore, "SetProcessDpiAwareness");
auto setter = (decltype(&SetProcessDpiAwareness))Lumix::os::getLibrarySymbol(shcore, "SetProcessDpiAwareness");
if (setter) setter(PROCESS_PER_MONITOR_DPI_AWARE);
}
@ -18,6 +15,6 @@ int main(int argc, char* argv[])
app->run();
const int exit_code = app->getExitCode();
Lumix::StudioApp::destroy(*app);
if(shcore) FreeLibrary(shcore);
if(shcore) Lumix::os::unloadLibrary(shcore);
return exit_code;
}