🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Property accessors in mixins

Started by
14 comments, last by noizex 3 years, 3 months ago

Hello,

When I tried to define some property accessors in mixin class I got following error:

(10): The virtual property syntax is currently not supported for mixin classes

Anyone knows how hard would be to implement this support / if it's on some short term roadmap at all?

I'd like to be able to do following:

mixin class HasAnimatedModel
{
	string model
	{
		set
		{
			@model_ = Model(model);
		}
		
		get
		{
			model_.getName();	
		}
	}
	
	Model@ model_;
}

and then be able to use it in various classes like a composition via mixin inheritance to build from reusable blocks of code:

class Creature: Object, HasAnimatedModel
{
	Creature()
	{
	   model = "troll";
	}
}

Where are we and when are we and who are we?
How many people in how many places at how many times?
Advertisement

It's probably not too hard to implement, but with me being short on time I don't have any plans to implement this at the moment. Should you however give it a try and send me a patch I'll gladly merge it into the code. ?

Alternatively, use the syntax for normal functions, which should work, i.e:

mixin class HasAnimatedModel
{
	string @get_model() const property { return model_; }
	void set_model(model @value) property { @model_ = value; }
	Model@ model_;
}

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

@WitchLord Thanks! Your snippet works indeed, I didn't know it would make a differnece to use this notation. I see the line for RegisterVirtualProperty is commented out for some reason, I will try to have a look, but considering there is workaround to use properties with mixins, I probably won't make it a priority ?


Where are we and when are we and who are we?
How many people in how many places at how many times?

@witchlord - since we're in the mixin topic, I wanted to ask a quick question - do you think it's possible to support meta info wihin mixin class so it can be “merged” together with other meta info for the main class that inherits mixin? It would be useful as I strongly depend on meta data (for editor, persistency etc so I don't have to keep a separate definitions somewhere but it can be derived from the code itself) but also wanted to reuse as much as possible via mixins. Just a hint if you think this is possible or there are some big obstacles you can think of - it's doable I will give it a try.


Where are we and when are we and who are we?
How many people in how many places at how many times?

Everything is possible ?

Supporting meta data on mixin classes would require changes to the builder add-on. It would would have to be able to collect the meta-data found in the mixins, store it, and then identify all the classes that include the mixins so the meta-data can be added to these object types.

It's not a trivial change, but also not a very complex one. If you give it a try I'd gladly include it in the library.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

@WitchLord

Sorry for posting here but I don't think it deserves separate thread and I don't want to necro the old one, so just quick remark while we're on “meta” topic ?

I recently started implementing old idea of using meta data to drive various behaviours and I ran into problem where ScriptBuilder would not parse the meta out and cause syntax errors. I recalled we had some discussion on this and the support for multiple stacked meta info was added back then, but I also know my patch fixed one problem where “shared” “mixin” etc. keywords would not be skipped by meta info parser and literally disable entire shared class from finding meta data.

Here is the thread: https://www.gamedev.net/forums/topic/696462-metadata-in-scriptbuilder-splitting-code-in-client-server-architecture/?page=2

Could this be fixed too in ScriptBuilder? I already added some fix from that patch I provided back then, not sure if that's enough but it does the trick and it parses meta correctly:

string token;
token.assign(&modifiedScript[pos], len);
if (token == "shared" || token == "abstract" || token == "mixin")
{
	pos += len;
	continue;
}

Maybe this could be further used for storing meta on mixins, and could also be some sort of IGNORED_KEYWORDS array for elegance. I add it just around line 316 in ScriptBuilder.cpp, before the comment

// Check if class

Thanks!


Where are we and when are we and who are we?
How many people in how many places at how many times?

Of course. There is always room for further improvement.

The patch you refer to from the other thread was already checked-in as mentioned in the thread (rev 2498).

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

@WitchLord Yeah but I think it didn't include this code that allows parsing shared/abstract/mixin? I downloaded most recent AS version and it's failing to parse the meta from shared classes?


Where are we and when are we and who are we?
How many people in how many places at how many times?

Indeed. I'll have it fixed as soon as possible.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Hmm. Actually the code is already capable of parsing metadata for shared/abstract classes. Not for mixins, though, since that is useless anyway (at least until the logic outlined above is implemented).

The following test works and is part of the regression test suite already:

// Test metadata on external shared entities
	{
		bout.buffer = "";
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);

		asIScriptModule *mod = engine->GetModule("test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"shared class test {} \n"
			"shared interface intf {} \n"
			"shared enum boo {} \n"
			"shared void func() {} \n");
		r = mod->Build();
		if (r < 0)
			TEST_FAILED;
		
		CScriptBuilder builder;
		builder.StartNewModule(engine, "mod");
		builder.AddSectionFromMemory("test1",
			"[external test] \n"
			"external shared class test; \n"
			"[external intf] \n"
			"external shared interface intf; \n"
			"[external boo] \n"
			"external shared enum boo; \n"
			"[external func] \n"
			"external shared void func(); \n");

		r = builder.BuildModule();
		if (r < 0)
			TEST_FAILED;

		if (bout.buffer != "")
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		asITypeInfo *type = engine->GetModule("mod")->GetTypeInfoByName("test");
		if (type == 0)
			TEST_FAILED;
		else
		{
			int typeId = type->GetTypeId();
			vector<string> metadata = builder.GetMetadataForType(typeId);
			if (metadata[0] != "external test")
				TEST_FAILED;
		}

		vector<string> metadata = builder.GetMetadataForFunc(engine->GetModule("mod")->GetFunctionByName("func"));
		if (metadata[0] != "external func")
			TEST_FAILED;

		metadata = builder.GetMetadataForType(engine->GetModule("mod")->GetTypeInfoByName("boo")->GetTypeId());
		if (metadata[0] != "external boo")
			TEST_FAILED;

		metadata = builder.GetMetadataForType(engine->GetModule("mod")->GetTypeInfoByName("intf")->GetTypeId());
		if (metadata[0] != "external intf")
			TEST_FAILED;
	}

The decorators for the classes are skipped in the function CScriptBuilder::ExtractDeclaration on line 905:

	// Skip white spaces, comments, and leading decorators
	do
	{
		pos += len;
		t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len);
		token.assign(&modifiedScript[pos], len);
	} while ( t == asTC_WHITESPACE || t == asTC_COMMENT || 
	          token == "private" || token == "protected" || 
	          token == "shared" || token == "external" || 
	          token == "final" || token == "abstract" );

Can you give an example of a script that doesn't work with the latest WIP?

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement