How to get access to the instance variable within the Create event? - gml

I have this code in GML2 Create event
inst1 = instance_create_layer(100, 100, "Instances", obj_genus)
inst2 = instance_create_layer(200, 100, "Instances", obj_genus)
with inst1 {
txt = "Ying"
related = inst2
}
with inst2 {
txt = "Yang"
related = inst1
}
But I can't use inst1 or inst2 at this time. I get the follower error:
ERROR in
action number 1
of Create Event
for object obj_game:
Variable obj_genus.inst2(100006, -2147483648) not set before
reading it.
at gml_Object_obj_game_Create_0(line 5)- related = inst2
##################
gml_Object_obj_game_Create_0 (line 5)
I create pairs of objects which are related to each other. Is it possible to wait in the Create event, until the object has been created? Unfortunately there is no Post Create event or something like that.

Your problem is not related to instance creation, but rather to the with statement - see, with changes what the current instance will be in the block, therefore as of related = inst2 line you are not pulling the inst2 variable from obj_game, but rather from obj_genus that you apply the statement on.
Using local variables (which you have found yourself) is by far the easiest way around this, as local variables are function/event-wide and thus remain perfectly accessible inside a with-block.
If you do need those two instances stored in obj_game for later use, you could use other.:
inst1 = instance_create_layer(100, 100, "Instances", obj_genus)
inst2 = instance_create_layer(200, 100, "Instances", obj_genus) // stores inst2 in obj_game
with inst1 {
txt = "Ying"
related = other.inst2 // uses inst2 from obj_game
}
with inst2 {
txt = "Yang"
related = other.inst1
}

In addition to YellowAfterlife's comment, this situation probably could avoid using the "with" construct entirely, and you could get away with this instead:
inst1 = instance_create_layer(100, 100, "Instances", obj_genus)
inst2 = instance_create_layer(200, 100, "Instances", obj_genus)
inst1.txt = "Ying"
inst1.related = inst2
inst2.txt = "Yang"
inst2.related = inst1
You're correct that there isn't anything like post-create event, and how you are doing it is the correct and standard way of passing data to an instance.
(On a side note I highly recommend getting in the habit of putting a semicolon ; at the end of every line. GML is pretty forgiving and usually lets you skip it, but most languages aren't, including GLSL which is how you program shaders in both GMS1 and 2.)

I just found out that it will work fine when is use var. I have no idea why it is so. var means that a variable is only available in this event and will be deleted when the event finished.
var inst1 = instance_create_layer(100, 100, "Instances", obj_genus)
var inst2 = instance_create_layer(200, 100, "Instances", obj_genus)
with inst1 {
txt = "Ying"
related = inst2
}
with inst2 {
txt = "Yang"
related = inst1
}

Related

Createjs. Line follow element fiddle

I created this jsfiddle.
A line i connecting two elements, and I want the line to stay connected to both elements no matter where they go.
I've sort of succeeded, but with one pretty obvious error. It keeps drawing new lines instead of redrawing the existing line. Please help me on how to make it update the line position instead.
var stage = new createjs.Stage("canvas");
createjs.Ticker.setFPS(60);
createjs.Ticker.addEventListener("tick", tick);
var arrDots = [];
var arrLines = [];
var circle1 = new createjs.Shape().set({
x: stage.canvas.width/2,
y: 50,
cursor: "pointer",
name:"target"
});
circle1.graphics.f(createjs.Graphics.getRGB(Math.random()*0xFFFFFF))
.dc(0,0,20);
stage.addChild(circle1);
arrDots.push(circle1);
var circle2 = new createjs.Shape().set({
x: stage.canvas.width/2,
y: stage.canvas.height - 50,
cursor: "pointer",
name:"target"
});
circle2.graphics.f(createjs.Graphics.getRGB(Math.random()*0xFFFFFF))
.dc(0,0,20);
stage.addChild(circle2);
arrDots.push(circle2);
var line = new createjs.Shape().set({
graphics: new createjs.Graphics().s("#00f").mt(arrDots[0].x,
arrDots[0].y).lt(arrDots[1].x, arrDots[1].y)
});
stage.addChild(line);
arrLines.push([arrDots[0], arrDots[1], line]);
createjs.Tween.get(circle1, {loop: true}).to({x:50},
3000).to({x:stage.canvas.width/2}, 3000);
function tick(event) {
keepLineConnection();
stage.update();
}
function keepLineConnection() {
for(var i = 0; i < arrLines.length; i++) {
arrLines[i][2].graphics.mt(arrLines[i][0].x, arrLines[i][0].y).lt(arrLines[i][1].x, arrLines[i][1].y);
}
}
The reason it keeps drawing is because you keep adding commmands to the graphics. Basically, you are doing this:
graphics.mt().lt().mt().lt().mt().lt().mt().etc();
Since you are just adding new instrucitons, they will pile up over time,
and will eventually kill your processor.
An easy fix for that is to clear the graphics first before adding new ones:
graphics.clear().mt().lt();
A better approach is to use commands. Since EaselJS 0.7.0, all graphics commands are objects, and at any time you can update properties of those objects directly. For example, the MoveTo and LineTo commands both have an x and y property. Here is more info on Commands: http://blog.createjs.com/update-width-height-in-easeljs/
Here is a modified fiddle that stores of commands on the line, and then updates them on tick. I also made a few other updates, such as changing the timing mode to RAF, which is smoother than using interval-based timers at 60FPS.
https://jsfiddle.net/tck7x8u2/
// Store commands:
line.cmd1 = line.graphics.mt(0,0).command;
line.cmd2 = line.graphics.lt(0,0).command;
// Update commands:
var instr = arrLines[i],
line = instr[2];
line.cmd1.x = instr[0].x;
line.cmd1.y = instr[0].y;
line.cmd2.x = instr[1].x;
line.cmd2.y = instr[1].y;
Cheers!
Edit: Here is are some demos using that idea that I made a while back:
https://lab.gskinner.com/connections
http://jsfiddle.net/lannymcnie/2xoL08bx/
http://jsfiddle.net/lannymcnie/6rh7P/

Grid Events and oldValue versus newValue

When updating entities in my cache, the oldValue=newValue in the event, unless I do a put with the original object instance. This is of course not always possible.
Here is a simplified example.
IgnitePredicate<CacheEvent> locLsnr = evt -> {
// do something
};
ignite.events().localListen(locLsnr,EventType.EVT_CACHE_OBJECT_PUT);
IgniteCache<TradeKey, Trade> cache = ignite.getOrCreateCache("MyCache");
Trade trade1 = new Trade();
trade1.setId(1);
trade1.setSize(10);
cache.put(new TradeKey(trade.getId()), trade1);
// event is generated
//evt.oldValue is null, no problem
trade1.setSize(20);
cache.put(new TradeKey(trade.getId()), trade1);
// event is generated
// evt.oldValue().getSize() is 10, evt.newValue().getSize() is 20, this is GOOD
But, if I retrieve the trade from the cache again before updating (from another part of the application for example), I am not able to see what the old value was in the event. Old value will just show the new value.
IgnitePredicate<CacheEvent> locLsnr = evt -> {
// do something
};
ignite.events().localListen(locLsnr,EventType.EVT_CACHE_OBJECT_PUT);
IgniteCache<TradeKey, Trade> cache = ignite.getOrCreateCache("MyCache");
Trade trade1 = new Trade();
trade1.setId(1);
trade1.setSize(10);
cache.put(new TradeKey(trade.getId()), trade1);
// event is generated
//evt.oldValue is null, no problem
trade1 = cache.get(new TradeKey(1)); // or could be a query or any search on the cache
trade1.setSize(20);
cache.put(new TradeKey(trade.getId()),trade1);
// event is generated
// evt.oldValue().getSize() is 20, evt.newValue().getSize() is 20, this is BAD
Any advice?
Thanks.
This is also discussed on Apache Ignite user forum: http://apache-ignite-users.70518.x6.nabble.com/Grid-Events-and-oldValue-versus-newValue-td10577.html

Why does cacheTimeout setting of renderView() in ColdBox application have no effect?

I'm developing a ColdBox application with modules and wanted to use it's caching functionality to cache a view for some time.
component{
property name="moduleConfig" inject="coldbox:moduleConfig:mymodule";
...
function widget(event, rc, prc){
var viewData = this.getData();
return renderView(
view = "main/widget",
args = viewData,
cache = true,
cacheSuffix = ":" & moduleConfig.entryPoint,
cacheTimeout = 2
);
}
}
I tried to set the default caching config by adding the following info to my Cachebox.cfc and removed the cacheTimeout from the code above:
cacheBox = {
defaultCache = {
objectDefaultTimeout = 1, //two hours default
objectDefaultLastAccessTimeout = 1, //30 minutes idle time
useLastAccessTimeouts = false,
reapFrequency = 5,
freeMemoryPercentageThreshold = 0,
evictionPolicy = "LRU",
evictCount = 1,
maxObjects = 300,
objectStore = "ConcurrentStore", //guaranteed objects
coldboxEnabled = false
},
caches = {
// Named cache for all coldbox event and view template caching
template = {
provider = "coldbox.system.cache.providers.CacheBoxColdBoxProvider",
properties = {
objectDefaultTimeout = 1,
objectDefaultLastAccessTimeout = 1,
useLastAccessTimeouts = false,
reapFrequency = 5,
freeMemoryPercentageThreshold = 0,
evictionPolicy = "LRU",
evictCount = 2,
maxObjects = 300,
objectStore = "ConcurrentSoftReferenceStore" //memory sensitive
}
}
}
};
Though that didn't have any influence on the caching. I've also tried to add the config above to my Coldbox.cfc.
Even if I create a completely new test app via CommandBox via coldbox create app MyApp, then only set the the caching in Cachebox.cfc to one minute, set viewCaching = true in Coldbox.cfc, and set event.setView( view="main/index", cache=true ) in the Main.cfc, it doesn't work as expected.
No matter what I do, the view is always cached for at least 5 minutes.
Is there something I am missing?
Make sure you have enabled view caching in your ColdBox configuration. Go to the /config/ColdBox.cfc file and add this key:
coldbox = {
// Activate view caching
viewCaching = true
}
Also, did you mistype the name of the CFC you changed for the caching above? Those changes should be in the /config/CacheBox.cfc file, not in /config/ColdBox.cfc.
Obviously, also the the reapFrequency in the /config/ColdBox.cfc needs to be set to a smaller value in order to let the cache entry be removed earlier.
Though, as the documentation states:
The delay in minutes to produce a cache reap (Not guaranteed)
It is not guaranteed that the cached item it really removed after that time, so it can be that the cache is empty after 3 minutes even when reapFrequency is set to 1.

How to export, then access exported methods in Lua

I have a file, display.lua in which I have code to load some resources.
----display.lua
Resources = {}
function Resources:new(rootdir)
local newObj = {image = {}, audio = {}, root = ""}
newObj.root = rootdir
return setmetatable(newObj, self)
end
function Resources:getSpriteSheet(name)
--- etc etc etc
end
and then I have a game variable I use to store gamestate, this is within another file game.lua.
---game.lua
require "display.lua"
function Game:new()
local newObj = {mode = "", map = {}, player = {}, resources = {}}
self.__index = self
return setmetatable(newObj, self)
end
function Game:init()
self.resources = Resources:new("/home/example/etc/game/")
local spriteSheet = self.resources:getSpriteSheet("spritesheet.png")
end
I have access to the resources code via use of require. My issue is that within Game:init() I can't access Resources:getSpriteSheet(), the lua interpreter complains of "attempt to call method (getSpriteSheet) a nil value"
I assume here I would have to export the methods in Resources but I don't know how I'd go about doing this, as I'm quite new to Lua.
I think you want return setmetatable(newObj, {__index = self}) instead of return setmetatable(newObj, self).
Also, require "display.lua" should probably be require "display" and game.lua should have Game = {} somewhere at the top. With these changes your example works for me.

How to add extra data to a member in MDS?

I'm running MDS on a virtual machine and trying to access the service from my host OS.
I've been able to add something to the database but my data is all over the place and in the Master Data Manager (website) I don't see the new member.
I suppose I shouldn't be using Attributes but something else but what and how? Are there tutorials because I can't find any ...?
Here's the code I'm using:
International international = new International();
EntityMembers entityMembers = new EntityMembers();
// Set the modelId, versionId, and entityId.
entityMembers.ModelId = new Identifier { Name = modelName };
entityMembers.VersionId = new Identifier { Name = versionName };
entityMembers.EntityId = new Identifier { Name = entityName };
entityMembers.MemberType = memberType;
Collection<Member> members = new Collection<Member>();
Member aNewMember = new Member();
aNewMember.MemberId = new MemberIdentifier() { Name = employee.FullName, Code = aNewCode, MemberType = memberType };
Collection<MDS.Attribute> attributes = new Collection<MDS.Attribute>();
MDS.Attribute attrOrgUnit = new MDS.Attribute();
attrOrgUnit.Identifier = new Identifier() { Name = "OrganizationalUnit" };
attrOrgUnit.Value = employee.OrganizationalUnit;
attrOrgUnit.Type = AttributeValueType.String;
attributes.Add(attrOrgUnit);
aNewMember.Attributes = attributes.ToArray();
members.Add(aNewMember);
entityMembers.Members = members.ToArray();
// Create a new entity member
OperationResult operationResult = new OperationResult();
clientProxy.EntityMembersCreate(international, entityMembers, false, out operationResult);
HandleOperationErrors(operationResult);
I have been able to fix my own problem.
First of all: creating separate variables with collections and converting them to arrays afterwards is not necessary. The code from the tutorials works but fails to mention that, when adding the service reference, you have to configure it (right-click on the service reference -> configure) to use Collections as "Collection type" instead of arrays and to generate message contracts.
Second, the code above with the attributes is correct and works perfectly. The problem I had which failed to add messages with attributes was unrelated. It was a connection/authentication problem between my Host OS and Guest OS.
Hope this helps someone.