C4MapScriptAlgoPolygon::C4MapScriptAlgoPolygon(const C4PropList *props)
{
	// Get MAPALGO_Polygon properties
	C4Value vptx, vpty;
	props->GetProperty(P_X, &vptx); props->GetProperty(P_Y, &vpty);
	C4ValueArray *ptx = vptx.getArray(), *pty = vpty.getArray();
	if (!ptx || !pty || ptx->GetSize() != pty->GetSize())
		throw C4AulExecError("C4MapScriptAlgoPolygon: Expected two equally sized int arrays in properties \"X\" and \"Y\".");
	poly.resize(ptx->GetSize());
	for (int32_t i=0; i<ptx->GetSize(); ++i)
	{
		poly[i].x = ptx->GetItem(i).getInt();
		poly[i].y = pty->GetItem(i).getInt();
	}
	wdt = props->GetPropertyInt(P_Wdt);
	if (!wdt) wdt = 1;
	empty = !!props->GetPropertyInt(P_Empty);
	open = !!props->GetPropertyInt(P_Open);
	if (open && !empty) throw C4AulExecError("C4MapScriptAlgoPolygon: Only empty polygons may be open.");
}
Пример #2
0
C4ValueArray * C4Effect::GetProperties() const
{
	C4ValueArray * a = C4PropList::GetProperties();
	int i;
	i = a->GetSize();
	a->SetSize(i + 5);
	(*a)[i++] = C4VString(&::Strings.P[P_Name]);
	(*a)[i++] = C4VString(&::Strings.P[P_Priority]);
	(*a)[i++] = C4VString(&::Strings.P[P_Interval]);
	(*a)[i++] = C4VString(&::Strings.P[P_CommandTarget]);
	(*a)[i++] = C4VString(&::Strings.P[P_Time]);
	return a;
}
C4MapScriptAlgoModifier::C4MapScriptAlgoModifier(const C4PropList *props, int32_t min_ops, int32_t max_ops)
{
	// Evaluate "Op" property of all algos that take another algo or layer as an operand
	// Op may be a proplist or an array of proplists
	C4Value vops; int32_t n; C4ValueArray temp_ops;
	props->GetProperty(P_Op, &vops);
	C4ValueArray *ops = vops.getArray();
	if (!ops)
	{
		C4PropList *op = vops.getPropList();
		if (op)
		{
			temp_ops.SetItem(0, vops);
			ops = &temp_ops;
			n = 1;
		}
	}
	else
	{
		n = ops->GetSize();
	}
	if (!ops || n<min_ops || (max_ops && n>max_ops))
		throw C4AulExecError(FormatString("C4MapScriptAlgo: Expected between %d and %d operands in property \"Op\".", (int)min_ops, (int)max_ops).getData());
	operands.resize(n);
	try
	{
		// can easily crash this by building a recursive prop list
		// unfortunately, protecting against that is not trivial
		for (int32_t i=0; i<n; ++i)
		{
			C4MapScriptAlgo *new_algo = FnParAlgo(ops->GetItem(i).getPropList());
			if (!new_algo) throw C4AulExecError(FormatString("C4MapScriptAlgo: Operand %d in property \"Op\" not valid.", (int)i).getData());
			operands[i] = new_algo;
		}
	}
	catch (...)
	{
		Clear();
		throw;
	}
}
Пример #4
0
C4ValueArray *C4FindObject::FindMany(const C4ObjectList &Objs) {
  // Trivial case
  if (IsImpossible()) return new C4ValueArray();
  // Set up array
  C4ValueArray *pArray = new C4ValueArray(32);
  int32_t iSize = 0;
  // Search
  for (C4ObjectLink *pLnk = Objs.First; pLnk; pLnk = pLnk->Next)
    if (pLnk->Obj->Status)
      if (Check(pLnk->Obj)) {
        // Grow the array, if neccessary
        if (iSize >= pArray->GetSize()) pArray->SetSize(iSize * 2);
        // Add object
        (*pArray)[iSize++] = C4VObj(pLnk->Obj);
      }
  // Shrink array
  pArray->SetSize(iSize);
  // Recheck object status (may shrink array again)
  CheckObjectStatus(pArray);
  // Apply sorting
  if (pSort) pSort->SortObjects(pArray);
  return pArray;
}
Пример #5
0
// return is to be freed by the caller
C4ValueArray *C4FindObject::FindMany(const C4ObjectList &Objs, const C4LSectors &Sct)
{
	// Trivial case
	if (IsImpossible())
		return new C4ValueArray();
	C4Rect *pBounds = GetBounds();
	if (!pBounds)
		return FindMany(Objs);
	// Prepare for array that may be generated
	C4ValueArray *pArray; int32_t iSize;
	// Check shape lists?
	if (UseShapes())
	{
		// Get area
		C4LArea Area(&::Objects.Sectors, *pBounds); C4LSector *pSct;
		C4ObjectList *pLst = Area.FirstObjectShapes(&pSct);
		// Check if a single-sector check is enough
		if (!Area.Next(pSct))
			return FindMany(pSct->ObjectShapes);
		// Set up array
		pArray = new C4ValueArray(32); iSize = 0;
		// Create marker, search all areas
		uint32_t iMarker = ::Objects.GetNextMarker();
		for (; pLst; pLst=Area.NextObjectShapes(pLst, &pSct))
			for (C4Object *obj : *pLst)
				if (obj->Status)
					if (obj->Marker != iMarker)
					{
						obj->Marker = iMarker;
						if (Check(obj))
						{
							// Grow the array, if neccessary
							if (iSize >= pArray->GetSize())
								pArray->SetSize(iSize * 2);
							// Add object
							(*pArray)[iSize++] = C4VObj(obj);
						}
					}
	}
	else
	{
		// Set up array
		pArray = new C4ValueArray(32); iSize = 0;
		// Search
		C4LArea Area(&::Objects.Sectors, *pBounds); C4LSector *pSct;
		for (C4ObjectList *pLst=Area.FirstObjects(&pSct); pLst; pLst=Area.NextObjects(pLst, &pSct))
			for (C4Object *obj : *pLst)
				if (obj->Status)
					if (Check(obj))
					{
						// Grow the array, if neccessary
						if (iSize >= pArray->GetSize())
							pArray->SetSize(iSize * 2);
						// Add object
						(*pArray)[iSize++] = C4VObj(obj);
					}
	}
	// Shrink array
	pArray->SetSize(iSize);
	// Recheck object status (may shrink array again)
	CheckObjectStatus(pArray);
	// Apply sorting
	if (pSort) pSort->SortObjects(pArray);
	return pArray;
}
bool C4EditCursor::DoContextMenu(DWORD dwKeyState)
{
	bool fObjectSelected = !!Selection.ObjectCount();
#ifdef USE_WIN32_WINDOWS
	POINT point; GetCursorPos(&point);
	HMENU hContext = GetSubMenu(hMenu,0);
	SetMenuItemEnable( hContext, IDM_VIEWPORT_DELETE, fObjectSelected && Console.Editing);
	SetMenuItemEnable( hContext, IDM_VIEWPORT_DUPLICATE, fObjectSelected && Console.Editing);
	SetMenuItemEnable( hContext, IDM_VIEWPORT_CONTENTS, fObjectSelected && Selection.GetObject()->Contents.ObjectCount() && Console.Editing);
	SetMenuItemText(hContext,IDM_VIEWPORT_DELETE,LoadResStr("IDS_MNU_DELETE"));
	SetMenuItemText(hContext,IDM_VIEWPORT_DUPLICATE,LoadResStr("IDS_MNU_DUPLICATE"));
	SetMenuItemText(hContext,IDM_VIEWPORT_CONTENTS,LoadResStr("IDS_MNU_CONTENTS"));

	ObjselectDelItems();
	C4FindObjectAtPoint pFO(X,Y);
	C4ValueArray * atcursor; atcursor = pFO.FindMany(::Objects, ::Objects.Sectors); // needs freeing (single object ptr)
	int itemcount = atcursor->GetSize();
	if(itemcount > 0)
	{
		const int maxitems = 25; // Maximum displayed objects. if you raise it, also change note with IDM_VPORTDYN_FIRST in resource.h
		if(itemcount > maxitems) itemcount = maxitems+1;
		itemsObjselect.resize(itemcount+1); // +1 for a separator
		itemsObjselect[0].ItemId = IDM_VPORTDYN_FIRST;
		itemsObjselect[0].Object = NULL;
		AppendMenu(hContext, MF_SEPARATOR, IDM_VPORTDYN_FIRST, NULL);
		int i = 1;
		for(std::vector<ObjselItemDt>::iterator it = itemsObjselect.begin() + 1; it != itemsObjselect.end(); ++it, ++i)
		{
			C4Object * obj = (*atcursor)[i-1].getObj();
			assert(obj);
			it->ItemId = IDM_VPORTDYN_FIRST+i;
			it->Object = obj;
			AppendMenu(hContext, MF_STRING, it->ItemId, FormatString("%s #%i (%i/%i)", obj->GetName(), obj->Number, obj->GetX(), obj->GetY()).GetWideChar());
		}
		if(atcursor->GetSize() > maxitems)
		{
			AppendMenu(hContext, MF_GRAYED, IDM_VPORTDYN_FIRST+maxitems+1, L"...");
			itemsObjselect[maxitems+1].ItemId = IDM_VPORTDYN_FIRST+maxitems+1;
			itemsObjselect[maxitems+1].Object = NULL;
		}
	}
	delete atcursor;

	int32_t iItem = TrackPopupMenu(
	                  hContext,
	                  TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_NONOTIFY,
	                  point.x,point.y, 0,
	                  Console.hWindow,
	                  NULL);
	switch (iItem)
	{
	case IDM_VIEWPORT_DELETE: Delete(); break;
	case IDM_VIEWPORT_DUPLICATE: Duplicate(); break;
	case IDM_VIEWPORT_CONTENTS: GrabContents(); break;
	case 0: break;
	default:
		for(std::vector<ObjselItemDt>::iterator it = itemsObjselect.begin() + 1; it != itemsObjselect.end(); ++it)
			if(it->ItemId == iItem)
			{
				DoContextObjsel(it->Object, (dwKeyState & MK_SHIFT) == 0);
				break;
			}
		break;
	}
	ObjselectDelItems();
#else
#ifdef WITH_DEVELOPER_MODE
	gtk_widget_set_sensitive(itemDelete, fObjectSelected && Console.Editing);
	gtk_widget_set_sensitive(itemDuplicate, fObjectSelected && Console.Editing);
	gtk_widget_set_sensitive(itemGrabContents, fObjectSelected && Selection.GetObject()->Contents.ObjectCount() && Console.Editing);

	ObjselectDelItems();
	C4FindObjectAtPoint pFO(X,Y);
	C4ValueArray * atcursor; atcursor = pFO.FindMany(::Objects, ::Objects.Sectors); // needs freeing
	int itemcount = atcursor->GetSize();
	if(itemcount > 0)
	{
		itemsObjselect.resize(itemcount+1); // +1 for a separator
		itemsObjselect[0].MenuItem = gtk_separator_menu_item_new();
		itemsObjselect[0].EditCursor = this;
		gtk_menu_shell_append(GTK_MENU_SHELL(menuContext), itemsObjselect[0].MenuItem);
		int i = 0;
		for(std::vector<ObjselItemDt>::iterator it = itemsObjselect.begin() + 1; it != itemsObjselect.end(); ++it, ++i)
		{
			it->EditCursor = this;
			C4Object * obj = (*atcursor)[i].getObj();
			assert(obj);
			it->Object = obj;
			GtkWidget * wdg = gtk_menu_item_new_with_label(FormatString("%s #%i (%i/%i)", obj->GetName(), obj->Number, obj->GetX(), obj->GetY()).getData());
			it->MenuItem = wdg;
			gtk_menu_shell_append(GTK_MENU_SHELL(menuContext), wdg);
			g_signal_connect(G_OBJECT(wdg), "activate", G_CALLBACK(OnObjselect), &*it);
		}
	}
	delete atcursor;
	gtk_widget_show_all(menuContext);

	gtk_menu_popup(GTK_MENU(menuContext), NULL, NULL, NULL, NULL, 3, 0);
#endif
#endif
	return true;
}
Пример #7
0
void C4ParticleValueProvider::Set(const C4ValueArray &fromArray)
{
	startValue = endValue = 1.0f;
	valueFunction = &C4ParticleValueProvider::Const;

	size_t arraySize = (size_t) fromArray.GetSize();
	if (arraySize < 2) return;

	int type = fromArray[0].getInt();

	switch (type)
	{
	case C4PV_Const:
		if (arraySize >= 2)
		{
			SetType(C4PV_Const);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::startValue);
		}
		break;

	case C4PV_Linear:
		if (arraySize >= 3)
		{
			SetType(C4PV_Linear);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::startValue);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::endValue);
		}
		break;
	case C4PV_Random:
		if (arraySize >= 3)
		{
			SetType(C4PV_Random);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::startValue);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::endValue);
			if (arraySize >= 4)
				SetParameterValue(VAL_TYPE_INT, fromArray[3], 0, &C4ParticleValueProvider::rerollInterval);
			alreadyRolled = 0;
		}
		break;
	case C4PV_Direction:
		if (arraySize >= 2)
		{
			SetType(C4PV_Direction);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::startValue);
		}
		break;
	case C4PV_Step:
		if (arraySize >= 4)
		{
			SetType(C4PV_Step);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::startValue);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::currentValue);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[3], &C4ParticleValueProvider::delay);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[4], &C4ParticleValueProvider::maxValue);
			if (delay == 0.f) delay = 1.f;
		}
		break;
	case C4PV_KeyFrames:
		if (arraySize >= 5)
		{
			SetType(C4PV_KeyFrames);
			SetParameterValue(VAL_TYPE_INT, fromArray[1], 0,  &C4ParticleValueProvider::smoothing);
			keyFrames.resize(arraySize + 4 - 1); // 2*2 additional information floats at the beginning and ending, offset the first array item, though

			keyFrameCount = 0;
			const size_t startingOffset = 2;
			size_t i = startingOffset;
			for (; i < arraySize; ++i)
			{
				SetParameterValue(VAL_TYPE_KEYFRAMES, fromArray[(int32_t)i], 0, 0, 2 + i - startingOffset);
			}
			keyFrameCount = (i - startingOffset) / 2 + 2;

			startValue = keyFrames[2 + 1];
			endValue = keyFrames[2 * keyFrameCount - 1];

			// add two points for easier interpolation at beginning and ending
			keyFrames[0] = -500.f;
			keyFrames[1] = keyFrames[2 + 1];
			keyFrames[2 * keyFrameCount - 2] = 1500.f;
			keyFrames[2 * keyFrameCount - 1] = keyFrames[keyFrameCount - 1 - 2];

		}
		break;
	case C4PV_Sin:
		if (arraySize >= 3)
		{
			SetType(C4PV_Sin); // Sin(parameterValue) * maxValue + startValue
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::parameterValue);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::maxValue);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[3], &C4ParticleValueProvider::startValue);
		}
		break;
	case C4PV_Speed:
		if (arraySize >= 3)
		{
			SetType(C4PV_Speed);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::speedFactor);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::startValue);
		}
		break;
	case C4PV_Wind:
		if (arraySize >= 3)
		{
			SetType(C4PV_Wind);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::speedFactor);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::startValue);
		}
		break;
	case C4PV_Gravity:
		if (arraySize >= 3)
		{
			SetType(C4PV_Gravity);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[1], &C4ParticleValueProvider::speedFactor);
			SetParameterValue(VAL_TYPE_FLOAT, fromArray[2], &C4ParticleValueProvider::startValue);
		}
		break;
	default:
		throw C4AulExecError("invalid particle value provider supplied");
		break;
	}
}