Reflection rework (#1357)
new reflection system - faster to compiler, saner errors
This commit is contained in:
parent
b2ea3536cb
commit
4bf33479b1
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "engine/hash_map.h"
|
||||
#include "engine/math.h"
|
||||
#include "engine/resource.h"
|
||||
#include "engine/string.h"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 = ∝
|
||||
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 = ∝
|
||||
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 = ∝
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 :(
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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&)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue