Ejemplo n.º 1
0
BOOL OperationHistory::ReduceSize(UINT32 MaxHistorySize, BOOL ExcludeLastUndo, BOOL DeleteWhatYouCan /*= FALSE*/)
{
    // If the Current size of the operation history is less than or equal to MaxHistorySize then
    // there is no need to do anything.
    if ((CurrentSize <= MaxHistorySize))
        return (TRUE);

    // If The NowPtr is NULL then there are no undo operations to be deleted so return FALSE
    if (NowPtr == NULL)
        return (FALSE);

    // Calculate how many bytes we need to reduce the size of the Operation history by
    UINT32 Reduction = (CurrentSize - MaxHistorySize);

    //-------------------------------------------------------------------------------
    // Check if the operation history can be reduced to MaxHistorySize bytes or less

    // The OpSize total is the count of the number of bytes we can reduce the Operation
    // history by.
    UINT32 OpSizeTotal = 0;

    // We know that the NowPtr is not NULL so the oldest undo operation will be found at
    // the head of the OpHistoryList.
    ListItem* pOp = OpHistoryList.GetHead();

    // We are allowed to delete all operations from the head of the list
    // upto and excluding StopOp. StopOp is the last undo operation if the
    // ExcludeLastUndo flag is TRUE, else it is the first redo operation.
    ListItem* StopOp = (ExcludeLastUndo) ? NowPtr: OpHistoryList.GetNext(NowPtr);


    // Loop until we either hit StopOp or we have found enough operations to delete
    while ((pOp != StopOp) && (OpSizeTotal < Reduction))
    {
        // In a sane world this should always be true
        ENSURE(	pOp != NULL,
                "OperationHistory::ReduceSize: Pointer OperationHistory is NULL");

        // Increase the OpSizeTotal by the number of bytes of the current operation
        OpSizeTotal += ((Operation*)pOp)->GetSize();

        // Get the next operation
        pOp = OpHistoryList.GetNext(pOp);
    };

    //-------------------------------------------------------------------------------
    // Now if we can,  reduce the operation history size

    if ((OpSizeTotal >= Reduction) || (DeleteWhatYouCan && (OpSizeTotal != 0))) // The size can be reduced
    {
        // Start at the head of the OpHistoryList
        ListItem* pDeleteOp = OpHistoryList.GetHead();

#ifdef _DEBUG
        UINT32 TotalChk = 0;
#endif

        while (pDeleteOp != pOp)
        {
            DecSize(((Operation*)pDeleteOp)->GetSize());  // Reduce history size

#ifdef _DEBUG
            TotalChk += ((Operation*)pDeleteOp)->GetSize();
#endif
            ListItem* pNextDeleteOp = OpHistoryList.GetNext(pDeleteOp);

            // If the operation which is about to be deleted is the operation pointed to by the NowPtr
            // then it is the last undo operation, so set NowPtr to NULL.
            if (NowPtr == pDeleteOp)
                NowPtr = NULL;
            delete(OpHistoryList.RemoveItem(pDeleteOp));         // Delete the operation
            pDeleteOp = pNextDeleteOp;
        }

        // Defensive programming

#ifdef _DEBUG                       // Required because of TotalChk variable
        ENSURE(	OpSizeTotal == TotalChk,
                "OperationHistory::ReduceSize: OpSizeTotal != TotalChk");
#endif


        Reduced = TRUE;

        return (TRUE);
    }
    else
        return (FALSE); // Cannot reduce size of history to MaxHistorySize bytes or less
}
Ejemplo n.º 2
0
VfsPath CColladaManager::GetLoadablePath(const VfsPath& pathnameNoExtension, FileType type)
{
	std::wstring extn;
	switch (type)
	{
	case PMD: extn = L".pmd"; break;
	case PSA: extn = L".psa"; break;
		// no other alternatives
	}

	/*

	Algorithm:
	* Calculate hash of skeletons.xml and converter version.
	* Use CCacheLoader to check for archived or loose cached .pmd/psa.
	* If cached version exists:
		* Return pathname of cached .pmd/psa.
	* Else, if source .dae for this model exists:
		* Convert it to cached .pmd/psa.
		* If converter succeeded:
			* Return pathname of cached .pmd/psa.
		* Else, fail (return empty path).
	* Else, if uncached .pmd/psa exists:
		* Return pathname of uncached .pmd/psa.
	* Else, fail (return empty path).

	Since we use CCacheLoader which automatically hashes file size and mtime,
	and handles archived files and loose cache, when preparing the cache key
	we add converter version number (so updates of the converter cause
	regeneration of the .pmd/psa) and the global skeletons.xml file size and
	mtime, as modelers frequently change the contents of skeletons.xml and get
	perplexed if the in-game models haven't updated as expected (we don't know
	which models were affected by the skeletons.xml change, if any, so we just
	regenerate all of them)

	TODO (maybe): The .dae -> .pmd/psa conversion may fail (e.g. if the .dae is
	invalid or unsupported), but it may take a long time to start the conversion
	then realise it's not going to work. That will delay the loading of the game
	every time, which is annoying, so maybe it should cache the error message
	until the .dae is updated and fixed. (Alternatively, avoid having that many
	broken .daes in the game.)

	*/

	// Now we're looking for cached files
	CCacheLoader cacheLoader(m_VFS, extn);
	MD5 hash;
	u32 version;
	m->PrepareCacheKey(hash, version);

	VfsPath cachePath;
	VfsPath sourcePath = pathnameNoExtension.ChangeExtension(L".dae");
	Status ret = cacheLoader.TryLoadingCached(sourcePath, hash, version, cachePath);

	if (ret == INFO::OK)
		// Found a valid cached version
		return cachePath;

	// No valid cached version, check if we have a source .dae
	if (ret != INFO::SKIPPED)
	{
		// No valid cached version was found, and no source .dae exists
		ENSURE(ret < 0);

		// Check if source (uncached) .pmd/psa exists
		sourcePath = pathnameNoExtension.ChangeExtension(extn);
		if (m_VFS->GetFileInfo(sourcePath, NULL) != INFO::OK)
		{
			// Broken reference, the caller will need to handle this
			return L"";
		}
		else
		{
			return sourcePath;
		}
	}

	// No valid cached version was found - but source .dae exists
	// We'll try converting it

	// We have a source .dae and invalid cached version, so regenerate cached version
	if (! m->Convert(sourcePath, cachePath, type))
	{
		// The COLLADA converter failed for some reason, this will need to be handled
		//	by the caller
		return L"";
	}

	return cachePath;
}
Ejemplo n.º 3
0
void CGUIString::GenerateTextCall(const CGUI *pGUI,
								  SFeedback &Feedback,
								  CStrIntern DefaultFont,
								  const int &from, const int &to,
								  const bool FirstLine,
								  const IGUIObject *pObject) const
{
	// Reset width and height, because they will be determined with incrementation
	//  or comparisons.
	Feedback.Reset();

	// Check out which text chunk this is within.
	//bool match_found = false;
	std::vector<TextChunk>::const_iterator itTextChunk;
	for (itTextChunk=m_TextChunks.begin(); itTextChunk!=m_TextChunks.end(); ++itTextChunk)
	{
		// Get the area that is overlapped by both the TextChunk and
		//  by the from/to inputted.
		int _from, _to;
		_from = std::max(from, itTextChunk->m_From);
		_to = std::min(to, itTextChunk->m_To);

		// If from is larger than to, than they are not overlapping
		if (_to == _from && itTextChunk->m_From == itTextChunk->m_To)
		{
			// These should never be able to have more than one tag.
			ENSURE(itTextChunk->m_Tags.size()==1);

			// Now do second check
			//  because icons and images are placed on exactly one position
			//  in the words-list, it can be counted twice if placed on an
			//  edge. But there is always only one logical preference that
			//  we want. This check filters the unwanted.

			// it's in the end of one word, and the icon
			//  should really belong to the beginning of the next one
			if (_to == to && to >= 1)
			{
				if (GetRawString()[to-1] == ' ' ||
					GetRawString()[to-1] == '-' ||
					GetRawString()[to-1] == '\n')
					continue;
			}
			// This std::string is just a break
			if (_from == from && from >= 1)
			{
				if (GetRawString()[from] == '\n' &&
					GetRawString()[from-1] != '\n' &&
					GetRawString()[from-1] != ' ' &&
					GetRawString()[from-1] != '-')
					continue;
			}

			// Single tags
			if (itTextChunk->m_Tags[0].m_TagType == CGUIString::TextChunk::Tag::TAG_IMGLEFT)
			{
				// Only add the image if the icon exists.
				if (pGUI->IconExists(itTextChunk->m_Tags[0].m_TagValue))
				{
					Feedback.m_Images[SFeedback::Left].push_back(itTextChunk->m_Tags[0].m_TagValue);
				}
				else if (pObject)
				{
					LOGERROR(L"Trying to use an [imgleft]-tag with an undefined icon (\"%hs\").", itTextChunk->m_Tags[0].m_TagValue.c_str());
				}
			}
			else
			if (itTextChunk->m_Tags[0].m_TagType == CGUIString::TextChunk::Tag::TAG_IMGRIGHT)
			{
				// Only add the image if the icon exists.
				if (pGUI->IconExists(itTextChunk->m_Tags[0].m_TagValue))
				{
					Feedback.m_Images[SFeedback::Right].push_back(itTextChunk->m_Tags[0].m_TagValue);
				}
				else if (pObject)
				{
					LOGERROR(L"Trying to use an [imgright]-tag with an undefined icon (\"%hs\").", itTextChunk->m_Tags[0].m_TagValue.c_str());
				}
			}
			else
			if (itTextChunk->m_Tags[0].m_TagType == CGUIString::TextChunk::Tag::TAG_ICON)
			{
				// Only add the image if the icon exists.
				if (pGUI->IconExists(itTextChunk->m_Tags[0].m_TagValue))
				{
					// We'll need to setup a text-call that will point
					//  to the icon, this is to be able to iterate
					//  through the text-calls without having to
					//  complex the structure virtually for nothing more.
					SGUIText::STextCall TextCall;

					// Also add it to the sprites being rendered.
					SGUIText::SSpriteCall SpriteCall;

					// Get Icon from icon database in pGUI
					SGUIIcon icon = pGUI->GetIcon(itTextChunk->m_Tags[0].m_TagValue);

					CSize size = icon.m_Size;

					// append width, and make maximum height the height.
					Feedback.m_Size.cx += size.cx;
					Feedback.m_Size.cy = std::max(Feedback.m_Size.cy, size.cy);

					// These are also needed later
					TextCall.m_Size = size;
					SpriteCall.m_Area = size;

					// Handle additional attributes
					std::vector<TextChunk::Tag::TagAttribute>::const_iterator att_it;
					for(att_it = itTextChunk->m_Tags[0].m_TagAttributes.begin(); att_it != itTextChunk->m_Tags[0].m_TagAttributes.end(); ++att_it)
					{
						TextChunk::Tag::TagAttribute tagAttrib = (TextChunk::Tag::TagAttribute)(*att_it);

						if (tagAttrib.attrib == "displace" && !tagAttrib.value.empty())
						{	//Displace the sprite
							CSize displacement;
							// Parse the value
							if (!GUI<CSize>::ParseString(CStr(tagAttrib.value).FromUTF8(), displacement))
								LOGERROR(L"Error parsing 'displace' value for tag [ICON]");
							else
								SpriteCall.m_Area += displacement;

						}
						else if(tagAttrib.attrib == "tooltip")
						{
							SpriteCall.m_Tooltip = CStr(tagAttrib.value).FromUTF8();
						}
						else if(tagAttrib.attrib == "tooltip_style")
						{
							SpriteCall.m_TooltipStyle = CStr(tagAttrib.value).FromUTF8();
						}
					}

					SpriteCall.m_Sprite = icon.m_SpriteName;
					SpriteCall.m_CellID = icon.m_CellID;

					// Add sprite call
					Feedback.m_SpriteCalls.push_back(SpriteCall);

					// Finalize text call
					TextCall.m_pSpriteCall = &Feedback.m_SpriteCalls.back();

					// Add text call
					Feedback.m_TextCalls.push_back(TextCall);
				}
				else if (pObject)
				{
					LOGERROR(L"Trying to use an [icon]-tag with an undefined icon (\"%hs\").", itTextChunk->m_Tags[0].m_TagValue.c_str());
				}
			}
		}
		else
		if (_to > _from && !Feedback.m_NewLine)
		{
			SGUIText::STextCall TextCall;

			// Set defaults
			TextCall.m_Font = DefaultFont;
			TextCall.m_UseCustomColor = false;

			// Extract substd::string from RawString.
			TextCall.m_String = GetRawString().substr(_from, _to-_from);

			// Go through tags and apply changes.
			std::vector<CGUIString::TextChunk::Tag>::const_iterator it2;
			for (it2 = itTextChunk->m_Tags.begin(); it2 != itTextChunk->m_Tags.end(); ++it2)
			{
				if (it2->m_TagType == CGUIString::TextChunk::Tag::TAG_COLOR)
				{
					// Set custom color
					TextCall.m_UseCustomColor = true;

					// Try parsing the color std::string
					if (!GUI<CColor>::ParseString(CStr(it2->m_TagValue).FromUTF8(), TextCall.m_Color))
					{
						if (pObject)
							LOGERROR(L"Error parsing the value of a [color]-tag in GUI text when reading object \"%hs\".", pObject->GetPresentableName().c_str());
					}
				}
				else
				if (it2->m_TagType == CGUIString::TextChunk::Tag::TAG_FONT)
				{
					// TODO Gee: (2004-08-15) Check if Font exists?
					TextCall.m_Font = CStrIntern(it2->m_TagValue);
				}
			}

			// Calculate the size of the font
			CSize size;
			int cx, cy;
			CFontMetrics font (TextCall.m_Font);
			font.CalculateStringSize(TextCall.m_String.c_str(), cx, cy);
			// For anything other than the first line, the line spacing
			// needs to be considered rather than just the height of the text
			if (! FirstLine)
				cy = font.GetLineSpacing();

			size.cx = (float)cx;
			size.cy = (float)cy;

			// Append width, and make maximum height the height.
			Feedback.m_Size.cx += size.cx;
			Feedback.m_Size.cy = std::max(Feedback.m_Size.cy, size.cy);

			// These are also needed later
			TextCall.m_Size = size;

			if (! TextCall.m_String.empty())
			{
				if (TextCall.m_String[0] == '\n')
				{
					Feedback.m_NewLine = true;
				}
			}

			// Add text-chunk
			Feedback.m_TextCalls.push_back(TextCall);
		}
	}
}
Ejemplo n.º 4
0
// This returns a shared_ptr to make sure the CGUI doesn't get deallocated
// while we're in the middle of calling a function on it (e.g. if a GUI script
// calls SwitchPage)
shared_ptr<CGUI> CGUIManager::top() const
{
	ENSURE(m_PageStack.size());
	return m_PageStack.back().gui;
}
Ejemplo n.º 5
0
void CControlBar::OnTimer(UINT_PTR nIDEvent)
{
	if (GetKeyState(VK_LBUTTON) < 0)
		return;

	AFX_MODULE_THREAD_STATE* pModuleThreadState = AfxGetModuleThreadState();

	// get current mouse position for hit test
	CPoint point; GetCursorPos(&point);
	ScreenToClient(&point);
	INT_PTR nHit = OnToolHitTest(point, NULL);
	if (nHit >= 0)
	{
		CWnd *pParent=GetTopLevelParent();
		// determine if status bar help should go away
        if(!IsTopParentActive())
        {
            nHit=-1;
        }
        else
        {
			ENSURE(pParent);
		    if(!pParent->IsWindowEnabled())
            {
			    nHit = -1;
            }
        }

		// remove status help if capture is set
		HWND hWndTip = pModuleThreadState->m_pToolTip->GetSafeHwnd();
		CWnd* pCapture = GetCapture();
		if (pCapture != this && pCapture->GetSafeHwnd() != hWndTip &&
			pCapture->GetTopLevelParent() == pParent)
		{
			nHit = -1;
		}
	}
	else
	{
		pModuleThreadState->m_nLastStatus = static_cast<INT_PTR>(-1);
	}

	// make sure it isn't over some other app's window
	if (nHit >= 0)
	{
		ClientToScreen(&point);
		HWND hWnd = ::WindowFromPoint(point);
		if (hWnd == NULL || (hWnd != m_hWnd && !::IsChild(m_hWnd, hWnd) &&
			pModuleThreadState->m_pToolTip->GetSafeHwnd() != hWnd))
		{
			nHit = -1;
			pModuleThreadState->m_nLastStatus = static_cast<INT_PTR>(-1);
		}
	}

	// handle the result
	if (nHit < 0)
	{
		if (pModuleThreadState->m_nLastStatus == static_cast<INT_PTR>(-1))
			KillTimer(ID_TIMER_CHECK);
		SetStatusText(static_cast<INT_PTR>(-1));
	}

	// set status text after initial timeout
	if (nIDEvent == ID_TIMER_WAIT)
	{
		KillTimer(ID_TIMER_WAIT);
		if (nHit >= 0)
			SetStatusText(nHit);
	}
}
Ejemplo n.º 6
0
void ShaderModelRenderer::Render(const RenderModifierPtr& modifier, const CShaderDefines& context, int flags)
{
	if (m->submissions.empty())
		return;

	CMatrix3D worldToCam;
	g_Renderer.GetViewCamera().m_Orientation.GetInverse(worldToCam);

	/*
	 * Rendering approach:
	 * 
	 * m->submissions contains the list of CModels to render.
	 * 
	 * The data we need to render a model is:
	 *  - CShaderTechnique
	 *  - CTexture
	 *  - CShaderUniforms
	 *  - CModelDef (mesh data)
	 *  - CModel (model instance data)
	 * 
	 * For efficient rendering, we need to batch the draw calls to minimise state changes.
	 * (Uniform and texture changes are assumed to be cheaper than binding new mesh data,
	 * and shader changes are assumed to be most expensive.)
	 * First, group all models that share a technique to render them together.
	 * Within those groups, sub-group by CModelDef.
	 * Within those sub-groups, sub-sub-group by CTexture.
	 * Within those sub-sub-groups, sub-sub-sub-group by CShaderUniforms.
	 * 
	 * Alpha-blended models have to be sorted by distance from camera,
	 * then we can batch as long as the order is preserved.
	 * Non-alpha-blended models can be arbitrarily reordered to maximise batching.
	 * 
	 * For each model, the CShaderTechnique is derived from:
	 *  - The current global 'context' defines
	 *  - The CModel's material's defines
	 *  - The CModel's material's shader effect name
	 * 
	 * There are a smallish number of materials, and a smaller number of techniques.
	 * 
	 * To minimise technique lookups, we first group models by material,
	 * in 'materialBuckets' (a hash table).
	 * 
	 * For each material bucket we then look up the appropriate shader technique.
	 * If the technique requires sort-by-distance, the model is added to the
	 * 'sortByDistItems' list with its computed distance.
	 * Otherwise, the bucket's list of models is sorted by modeldef+texture+uniforms,
	 * then the technique and model list is added to 'techBuckets'.
	 * 
	 * 'techBuckets' is then sorted by technique, to improve batching when multiple
	 * materials map onto the same technique.
	 * 
	 * (Note that this isn't perfect batching: we don't sort across models in
	 * multiple buckets that share a technique. In practice that shouldn't reduce
	 * batching much (we rarely have one mesh used with multiple materials),
	 * and it saves on copying and lets us sort smaller lists.)
	 * 
	 * Extra tech buckets are added for the sorted-by-distance models without reordering.
	 * Finally we render by looping over each tech bucket, then looping over the model
	 * list in each, rebinding the GL state whenever it changes.
	 */

 	typedef boost::unordered_map<SMRMaterialBucketKey, std::vector<CModel*>, SMRMaterialBucketKeyHash> MaterialBuckets_t;
	MaterialBuckets_t materialBuckets;

	{
		PROFILE3("bucketing by material");

		for (size_t i = 0; i < m->submissions.size(); ++i)
		{
			CModel* model = m->submissions[i];
			
			CShaderDefines defs = model->GetMaterial().GetShaderDefines();
			CShaderConditionalDefines condefs = model->GetMaterial().GetConditionalDefines();
			
			for (size_t j = 0; j < condefs.GetSize(); ++j)
			{
				CShaderConditionalDefines::CondDefine &item = condefs.GetItem(j);
				int type = item.m_CondType;
				switch (type)
				{
					case DCOND_DISTANCE:
					{
						CVector3D modelpos = model->GetTransform().GetTranslation();
						float dist = worldToCam.Transform(modelpos).Z;
						
						float dmin = item.m_CondArgs[0];
						float dmax = item.m_CondArgs[1];
						
						if ((dmin < 0 || dist >= dmin) && (dmax < 0 || dist < dmax))
							defs.Add(item.m_DefName.c_str(), item.m_DefValue.c_str());
						
						break;
					}
				}
			}

			SMRMaterialBucketKey key(model->GetMaterial().GetShaderEffect(), defs);
			std::vector<CModel*>& bucketItems = materialBuckets[key];
			bucketItems.push_back(model);
		}
	}

	std::vector<SMRSortByDistItem> sortByDistItems;

	std::vector<CShaderTechniquePtr> sortByDistTechs;
		// indexed by sortByDistItems[i].techIdx
		// (which stores indexes instead of CShaderTechniquePtr directly
		// to avoid the shared_ptr copy cost when sorting; maybe it'd be better
		// if we just stored raw CShaderTechnique* and assumed the shader manager
		// will keep it alive long enough)

	std::vector<SMRTechBucket> techBuckets;

	{
		PROFILE3("processing material buckets");
		for (MaterialBuckets_t::iterator it = materialBuckets.begin(); it != materialBuckets.end(); ++it)
		{
			CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(it->first.effect, context, it->first.defines);

			// Skip invalid techniques (e.g. from data file errors)
			if (!tech)
				continue;

			if (tech->GetSortByDistance())
			{
				// Add the tech into a vector so we can index it
				// (There might be duplicates in this list, but that doesn't really matter)
				if (sortByDistTechs.empty() || sortByDistTechs.back() != tech)
					sortByDistTechs.push_back(tech);
				size_t techIdx = sortByDistTechs.size()-1;

				// Add each model into sortByDistItems
				for (size_t i = 0; i < it->second.size(); ++i)
				{
					SMRSortByDistItem itemWithDist;
					itemWithDist.techIdx = techIdx;

					CModel* model = it->second[i];
					itemWithDist.model = model;

					CVector3D modelpos = model->GetTransform().GetTranslation();
					itemWithDist.dist = worldToCam.Transform(modelpos).Z;

					sortByDistItems.push_back(itemWithDist);
				}
			}
			else
			{
				// Sort model list by modeldef+texture, for batching
				// TODO: This only sorts by base texture. While this is an OK approximation
				// for most cases (as related samplers are usually used together), it would be better
				// to take all the samplers into account when sorting here.
				std::sort(it->second.begin(), it->second.end(), SMRBatchModel());

				// Add a tech bucket pointing at this model list
				SMRTechBucket techBucket = { tech, &it->second[0], it->second.size() };
				techBuckets.push_back(techBucket);
			}
		}
	}

	{
		PROFILE3("sorting tech buckets");
		// Sort by technique, for better batching
		std::sort(techBuckets.begin(), techBuckets.end(), SMRCompareTechBucket());
	}

	// List of models corresponding to sortByDistItems[i].model
	// (This exists primarily because techBuckets wants a CModel**;
	// we could avoid the cost of copying into this list by adding
	// a stride length into techBuckets and not requiring contiguous CModel*s)
	std::vector<CModel*> sortByDistModels;

	if (!sortByDistItems.empty())
	{
		{
			PROFILE3("sorting items by dist");
			std::sort(sortByDistItems.begin(), sortByDistItems.end(), SMRCompareSortByDistItem());
		}

		{
			PROFILE3("batching dist-sorted items");

			sortByDistModels.reserve(sortByDistItems.size());

			// Find runs of distance-sorted models that share a technique,
			// and create a new tech bucket for each run

			size_t start = 0; // start of current run
			size_t currentTechIdx = sortByDistItems[start].techIdx;

			for (size_t end = 0; end < sortByDistItems.size(); ++end)
			{
				sortByDistModels.push_back(sortByDistItems[end].model);

				size_t techIdx = sortByDistItems[end].techIdx;
				if (techIdx != currentTechIdx)
				{
					// Start of a new run - push the old run into a new tech bucket
					SMRTechBucket techBucket = { sortByDistTechs[currentTechIdx], &sortByDistModels[start], end-start };
					techBuckets.push_back(techBucket);
					start = end;
					currentTechIdx = techIdx;
				}
			}

			// Add the tech bucket for the final run
			SMRTechBucket techBucket = { sortByDistTechs[currentTechIdx], &sortByDistModels[start], sortByDistItems.size()-start };
			techBuckets.push_back(techBucket);
		}
	}

	{
		PROFILE3("rendering bucketed submissions");

		size_t idxTechStart = 0;
		
		// This vector keeps track of texture changes during rendering. It is kept outside the
		// loops to avoid excessive reallocations. The token allocation of 64 elements 
		// should be plenty, though it is reallocated below (at a cost) if necessary.
		std::vector<CTexture*> currentTexs;
		currentTexs.reserve(64);
		
		// texBindings holds the identifier bindings in the shader, which can no longer be defined 
		// statically in the ShaderRenderModifier class. texBindingNames uses interned strings to
		// keep track of when bindings need to be reevaluated.
		std::vector<CShaderProgram::Binding> texBindings;
		texBindings.reserve(64);
		std::vector<CStrIntern> texBindingNames;
		texBindingNames.reserve(64);

		while (idxTechStart < techBuckets.size())
		{
			CShaderTechniquePtr currentTech = techBuckets[idxTechStart].tech;

			// Find runs [idxTechStart, idxTechEnd) in techBuckets of the same technique
			size_t idxTechEnd;
			for (idxTechEnd = idxTechStart + 1; idxTechEnd < techBuckets.size(); ++idxTechEnd)
			{
				if (techBuckets[idxTechEnd].tech != currentTech)
					break;
			}

			// For each of the technique's passes, render all the models in this run
			for (int pass = 0; pass < currentTech->GetNumPasses(); ++pass)
			{
				currentTech->BeginPass(pass);

				const CShaderProgramPtr& shader = currentTech->GetShader(pass);
				int streamflags = shader->GetStreamFlags();

				modifier->BeginPass(shader);

				m->vertexRenderer->BeginPass(streamflags);
				
				// When the shader technique changes, textures need to be
				// rebound, so ensure there are no remnants from the last pass.
				// (the vector size is set to 0, but memory is not freed)
				currentTexs.clear();
				texBindings.clear();
				texBindingNames.clear();
				
				CModelDef* currentModeldef = NULL;
				CShaderUniforms currentStaticUniforms;

				for (size_t idx = idxTechStart; idx < idxTechEnd; ++idx)
				{
					CModel** models = techBuckets[idx].models;
					size_t numModels = techBuckets[idx].numModels;
					for (size_t i = 0; i < numModels; ++i)
					{
						CModel* model = models[i];

						if (flags && !(model->GetFlags() & flags))
							continue;

						CMaterial::SamplersVector samplers = model->GetMaterial().GetSamplers();
						size_t samplersNum = samplers.size();
						
						// make sure the vectors are the right virtual sizes, and also
						// reallocate if there are more samplers than expected.
						if (currentTexs.size() != samplersNum)
						{
							currentTexs.resize(samplersNum, NULL);
							texBindings.resize(samplersNum, CShaderProgram::Binding());
							texBindingNames.resize(samplersNum, CStrIntern());
							
							// ensure they are definitely empty
							std::fill(texBindings.begin(), texBindings.end(), CShaderProgram::Binding());
							std::fill(currentTexs.begin(), currentTexs.end(), (CTexture*)NULL);
							std::fill(texBindingNames.begin(), texBindingNames.end(), CStrIntern());
						}
						
						// bind the samplers to the shader
						for (size_t s = 0; s < samplersNum; ++s)
						{
							CMaterial::TextureSampler &samp = samplers[s];
							
							CShaderProgram::Binding bind = texBindings[s];
							// check that the handles are current
							// and reevaluate them if necessary
							if (texBindingNames[s] == samp.Name && bind.Active())
							{
								bind = texBindings[s];
							}
							else
							{
								bind = shader->GetTextureBinding(samp.Name.c_str());		
								texBindings[s] = bind;
								texBindingNames[s] = samp.Name;
							}

							// same with the actual sampler bindings
							CTexture* newTex = samp.Sampler.get();
							if (bind.Active() && newTex != currentTexs[s])
							{
								shader->BindTexture(bind, samp.Sampler->GetHandle());
								currentTexs[s] = newTex;
							}
						}
						
						// Bind modeldef when it changes
						CModelDef* newModeldef = model->GetModelDef().get();
						if (newModeldef != currentModeldef)
						{
							currentModeldef = newModeldef;
							m->vertexRenderer->PrepareModelDef(shader, streamflags, *currentModeldef);
						}

						// Bind all uniforms when any change
						CShaderUniforms newStaticUniforms = model->GetMaterial().GetStaticUniforms();
						if (newStaticUniforms != currentStaticUniforms)
						{
							currentStaticUniforms = newStaticUniforms;
							currentStaticUniforms.BindUniforms(shader);
						}
						
						CShaderRenderQueries renderQueries = model->GetMaterial().GetRenderQueries();
						
						for (size_t q = 0; q < renderQueries.GetSize(); q++)
						{
							CShaderRenderQueries::RenderQuery rq = renderQueries.GetItem(q);
							if (rq.first == RQUERY_TIME)
							{
								CShaderProgram::Binding binding = shader->GetUniformBinding(rq.second);
								if (binding.Active())
								{
									double time = g_Renderer.GetTimeManager().GetGlobalTime();
									shader->Uniform(binding, time, 0,0,0);
								}
							}
							else if (rq.first == RQUERY_WATER_TEX)
							{
								WaterManager* WaterMgr = g_Renderer.GetWaterManager();
								double time = WaterMgr->m_WaterTexTimer;
								double period = 1.6;
								int curTex = (int)(time*60/period) % 60;
								
								if (WaterMgr->m_RenderWater && WaterMgr->WillRenderFancyWater())
									shader->BindTexture("waterTex", WaterMgr->m_NormalMap[curTex]);
								else
									shader->BindTexture("waterTex", g_Renderer.GetTextureManager().GetErrorTexture());
							}
							else if (rq.first == RQUERY_SKY_CUBE)
							{
								shader->BindTexture("skyCube", g_Renderer.GetSkyManager()->GetSkyCube());
							}
						}

						modifier->PrepareModel(shader, model);

						CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
						ENSURE(rdata->GetKey() == m->vertexRenderer.get());

						m->vertexRenderer->RenderModel(shader, streamflags, model, rdata);
					}
				}

				m->vertexRenderer->EndPass(streamflags);

				currentTech->EndPass(pass);
			}

			idxTechStart = idxTechEnd;
		}
	}
}
Ejemplo n.º 7
0
BOOL OutputDIB::WriteBlock( UINT32 YPos, UINT32 Height, LPBYTE BlockStart, UINT32 InputBPP,
							INT32 ProgressOffset)
{
	FNPTR_SCANLINE ConvertFn = NULL;
	LPBYTE Buffer = NULL;
	size_t BufSize = 0L;
	size_t ChunkHeight = 1;
	DIBConvert *DoConvert = NULL;

	// Set up the size and other information for the dib block that we require. This is
	// dependent on the export depth or bpp required.
	if ( !SetUpBlock( &BufSize, &ChunkHeight, &DoConvert, &ConvertFn ) )
		return FALSE;			// Error details already set up

	if (BufSize)
	{
		Buffer = (LPBYTE)CCMalloc( BufSize );
		if (Buffer==NULL)
			return FALSE;
	}

	if ( DoConvert )
	{
		// use new classes to do it
		// 8bpp, 4bpp and 1bpp conversion
		INT32 h = Height;
		INT32 count = 0;
		LPBYTE Data = BlockStart;
		const size_t SourceWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, InputBPP ) * ChunkHeight;
		const size_t DestWidth   = DIBUtil::ScanlineSize( BitmapInfo.biWidth, BitmapInfo.biBitCount );

		while (h)
		{
			ENSURE(h >= 0, "bad looping");

			const size_t ThisBit = min( h, (INT32)ChunkHeight );
			if (!DoConvert->Convert( Data, Buffer, ThisBit, IsFirstStrip ))
				break;								// stop if conversion failed

			IsFirstStrip = FALSE;

			OutputFile->write( Buffer, ThisBit * DestWidth );
			if (OutputFile->bad())
				break;								// stop if file errored
			Data += SourceWidth;
			h -= ThisBit;

			// now update the progress display, started with CurrentExportSize
			// CurrentExport size is now the point to go from in the export
			count++;
			ContinueSlowJob( (INT32)( ProgressOffset + count ));
			//ContinueSlowJob( (INT32)(100*count/(Height)) );
		}
	}
	// now the bytes (this is crying out for a virtual function or two)
	else if ( ConvertFn && Buffer )
	{
		// Write via conversion function
		// 24 bpp convert
		UINT32 h = Height;
		INT32 count = 0;
		LPBYTE Data = BlockStart;
		const size_t SourceWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, InputBPP );

		while (h)
		{
			ConvertFn( BitmapInfo.biWidth, Data, Buffer );
			OutputFile->write( Buffer, BufSize );
			if (OutputFile->bad())
				break;								// stop if file errored
			Data += SourceWidth;
			h -= ChunkHeight;

			// now update the progress display, started with CurrentExportSize
			// ProgressOffset size is now the point to go from in the export
			count++;
			ContinueSlowJob( (INT32)( ProgressOffset + count ));
			//ContinueSlowJob( (INT32)((CurrentExportSize * count)/Height) );
		}
	}
	else
	{
		// Write it all out in one go
		//OutputFile->write( BlockStart, BitmapInfo.biSizeImage );
		// Write the actual bytes out to file. Used to do it in one go but we really
		// require some progress bar indication so we will do it in chunks.
		DWORD BitsSize = BitmapInfo.biSizeImage; 
		if (BitsSize > 0)
		{
			if (BitsSize < 1024)
			{
				// File very small or no progress bar required, so load in one go
				OutputFile->write( BlockStart, BitsSize);
			}
			else
			{
				// Load in chunks, for present split into 100 chunks
				DWORD ChunkSize = BitsSize/100;
				DWORD Position = 0;
				LPBYTE pBitInfo = BlockStart;
				
				while (Position < BitsSize)
				{
					if ( (BitsSize - Position) > ChunkSize)
						OutputFile->write( pBitInfo, ChunkSize);
					else
					{
						ChunkSize = BitsSize - Position;
						OutputFile->write( pBitInfo, ChunkSize);
					}
							
					// Increment our counters/pointers
					Position+=ChunkSize;
					pBitInfo+=ChunkSize;
					// Progress bar started with height of bitmap
					ContinueSlowJob( (INT32)(ProgressOffset + (Height * Position)/BitsSize) );
					//ContinueSlowJob( (INT32)((CurrentExportSize * Position)/BitsSize) );
				}
			}
		}
	}

	// If present, get rid of our export function
	if (DoConvert)
	{
		delete DoConvert;
	 	DoConvert = NULL;
	}

	CCFree( Buffer );

	HeightWritten += Height;						// remember we wrote this lot

	return !OutputFile->bad();
}
Ejemplo n.º 8
0
void CInformErrorDialog::GetDialogInfo()
{
	// Skip this if we've already done it.
	if (ValidInfo)
		return;

	// Find out how bug the dialog is by default.
	CRect DlgRect;
	GetClientRect(&DlgRect);
	DialogSize.cx = DlgRect.Width();
	DialogSize.cy = DlgRect.Height();

	// Find out the button spacing/sizes etc.
	CWnd *pCtrl1 = GetDlgItem(ButtonID[0]);
	CWnd *pCtrl2 = GetDlgItem(ButtonID[1]);
	ENSURE((pCtrl1 != NULL) && (pCtrl2 != NULL), 
		   "Can't find control in CInformErrorDialog::OnInitDialog()");

	// Safety check.
	if ((pCtrl1 == NULL) || (pCtrl2 == NULL))
		return;

	// Get width of buttons, and the spacing between the buttons and the edge of the dialog.
	WINDOWPLACEMENT Placement;
	Placement.length = sizeof(WINDOWPLACEMENT);
	pCtrl1->GetWindowPlacement(&Placement);

	DefTopOfButton = Placement.rcNormalPosition.top;
	DefButtonSize.cx = Placement.rcNormalPosition.right - Placement.rcNormalPosition.left;
	DefButtonSize.cy = Placement.rcNormalPosition.bottom - Placement.rcNormalPosition.top;
	EdgeSpacing = Placement.rcNormalPosition.left;

	// Get space between adjacent buttons.
	Placement.length = sizeof(WINDOWPLACEMENT);
	pCtrl2->GetWindowPlacement(&Placement);

	ButtonSpacing = Placement.rcNormalPosition.left - (EdgeSpacing + DefButtonSize.cx);

	// Find the position of the icon.
	CWnd *pIconCtrl = GetDlgItem(_R(IDC_ERRORBOX_ICON));
	ENSURE(pIconCtrl != NULL, "Can't find Icon control in CInformErrorDialog::GetDialogInfo()");

	// Safety check.
	if (pIconCtrl == NULL)
		return;

	Placement.length = sizeof(WINDOWPLACEMENT);
	pIconCtrl->GetWindowPlacement(&Placement);
	
	DefIconPos.x = Placement.rcNormalPosition.left;
	DefIconPos.y = Placement.rcNormalPosition.top;

	// Find the position of the message text area.
	CWnd *pMsgCtrl = GetDlgItem(_R(IDC_ERRORBOX_TEXT));
	ENSURE(pMsgCtrl != NULL, "Can't find Text control in CInformErrorDialog::GetDialogInfo()");

	// Safety check.
	if (pMsgCtrl == NULL)
		return;

	Placement.length = sizeof(WINDOWPLACEMENT);
	pMsgCtrl->GetWindowPlacement(&Placement);

	DefMsgSize.cx = Placement.rcNormalPosition.right - Placement.rcNormalPosition.left;
	DefMsgSize.cy = Placement.rcNormalPosition.bottom - Placement.rcNormalPosition.top;

	// The static variables now contain valid information.
	ValidInfo = TRUE;
}
Ejemplo n.º 9
0
BOOL CInformErrorDialog::SetupButtons(HDC hDC, INT32 NumButtons)
{
	// Set the default button in the dialog.
	CWnd *pDefCtrl = GetDlgItem(ButtonID[m_OK - 1]);
	ENSURE(pDefCtrl != NULL, "Can't get handle to default control in CInformErrorDialog");

	// If we can't get at this button then ooer...bit of a fatal error
	if (pDefCtrl == NULL)
	{
		ENSURE(FALSE, "Can't get default button in error box!");
		return FALSE;
	}

	// Set the keyboard focus to the default button, and give it a 'default' border.
	pDefCtrl->SetFocus();
	SendMessage(DM_SETDEFID, ButtonID[m_OK - 1], 0);

	// Read in the button texts, and find which is the widest string.
	INT32 ButtonWidth = DefButtonSize.cx;
	INT32 i;
	for (i = 0; i < NumButtons; i++)
	{
		// Try to load text for this button
		if (!ButtonText[i].Load(m_ButtonStr[i], m_OwnerModule))
		{
			ENSURE(FALSE, "Unable to load button text for error box!");
			return FALSE;
		}

		// Try to read the size of this button text.
		SIZE TextSize;
		if (!GetTextExtentPoint(hDC, (TCHAR *) ButtonText[i], ButtonText[i].Length(),
						   	    &TextSize))
		{
			// Error reading text size
			ENSURE(FALSE, "Unable to read button text size for error box!");
			return FALSE;
		}

		if (TextSize.cx > ButtonWidth)
			ButtonWidth = TextSize.cx + 8;
	}

	// Allow for space on either side in the button
	ButtonWidth += 8;

	// Find out how big the buttons can be at the most.
	INT32 MaxWidth = DialogSize.cx - 
				   (2 * EdgeSpacing) - 
				   ((NumButtons - 1) * ButtonSpacing);

	// NumButtons cannot be 0 if we get to here...but just in case :-)
	if (NumButtons == 0)
	{
		ENSURE(FALSE, "NumButtons is zero in error box!");
		return FALSE;
	}

	// Safe to do a divide now!
	MaxWidth /= NumButtons;

	// The width of the dialog may change.
	INT32 NewWidth = DialogSize.cx;

	// Find out if we need to make the dialog bigger to accomodate the buttons.
	if (ButtonWidth > MaxWidth)
	{
		// Yes - find out if the buttons actually fit on screen - if not, make them
		// smaller and truncate the button text (this shouldn't happen too often!)

		// Get required dialog width
		NewWidth = (EdgeSpacing * 2) +
				   (NumButtons * ButtonWidth) +
				   ((NumButtons - 1) * ButtonSpacing);

		// Does this actually fit on screen?
		INT32 ScreenWidth = GetSystemMetrics(SM_CXSCREEN);

		if (ScreenWidth < NewWidth)
		{
			// They don't fit - downsize the buttons to fit.
			ButtonWidth = ScreenWidth - 
					      (2 * EdgeSpacing) - 
					      ((NumButtons - 1) * ButtonSpacing);
			ButtonWidth /= NumButtons;

			NewWidth = ScreenWidth;
		}

		// Ok - buttons are now correct size - resize the dialog.
		SIZE BorderSize;
		BorderSize.cx = 2 * ::GetSystemMetrics(SM_CXDLGFRAME);
		BorderSize.cy = ::GetSystemMetrics(SM_CYDLGFRAME) + 
						::GetSystemMetrics(SM_CYCAPTION);

		if (!SetWindowPos(NULL, 0, 0, 
					 	  NewWidth + BorderSize.cx, DialogSize.cy + BorderSize.cy,
					      SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW))
		{
			ENSURE(FALSE, "Unable to resize the error box!");
			return FALSE;
		}

		// Resize the error message control so it doesn't look silly.
		INT32 Diff = NewWidth - DialogSize.cx;
		
		CWnd *pMsgCtrl = GetDlgItem(_R(IDC_ERRORBOX_TEXT));
		ENSURE(pMsgCtrl != NULL, "Can't get handle to text control in CInformErrorDialog");

		if (pMsgCtrl != NULL)
		{
			// Ok - resize it.
			if (!pMsgCtrl->SetWindowPos(NULL, 0, 0, 
								   		DefMsgSize.cx + Diff, DefMsgSize.cy,
			  					   		SWP_NOACTIVATE | SWP_NOZORDER | 
			  					   		SWP_NOMOVE | SWP_NOREDRAW))
			{
				ENSURE(FALSE, "Unable to adjust error message control in error box!");
				return FALSE;
			}
		}
	}

	// Position buttons accordingly...

	// How much space is left on either side of the row of buttons?
	INT32 SpareSpace = NewWidth - 
					 (NumButtons * ButtonWidth) - 
					 ((NumButtons - 1) * ButtonSpacing);

	// Work out where the first button should be.
	INT32 FarLeft = SpareSpace / 2;

	INT32 ButtonStep = ButtonSpacing + ButtonWidth;

	// For each button:
	//  * Set the button text.
	//  * Move the button to the correct position.
	//  * Show the button.
	for (i = 0; i < NumButtons; i++)
	{
		SetDlgItemText(ButtonID[i], ButtonText[i]);

		if (!m_Button[i].SetWindowPos(NULL, 
								 	  FarLeft + (i * ButtonStep), DefTopOfButton, 
								 	  ButtonWidth, DefButtonSize.cy,
								 	  SWP_NOACTIVATE | SWP_NOZORDER | 
								 	  SWP_NOREDRAW | SWP_SHOWWINDOW))
		{
			ENSURE(FALSE, "Unable to move button in the error box!");
			return FALSE;
		}
	}

	// Tell the caller that we managed to do all this successfully!
	return TRUE;
}
Ejemplo n.º 10
0
u32 CNetServerTurnManager::GetSavedTurnLength(u32 turn)
{
	ENSURE(turn <= m_ReadyTurn);
	return m_SavedTurnLengths.at(turn);
}
Ejemplo n.º 11
0
void OpLayerChange::Do(OpDescriptor*)
{   
	ENSURE(FALSE,"This shouldn't have been called");
/*
	Spread* pSpread = Document::GetCurrent()->GetLayerMgr().GetCurrentSpread(); 
	// Find the first layer on the spread. All siblings of the first layer node should
	// be layer nodes
	Node* CurrentTreeLayer = pSpread->FindFirstLayer(); // skips over page nodes 

	ENSURE(CurrentTreeLayer->GetRuntimeClass() == CC_RUNTIME_CLASS(Layer), 
			"A next sibling of a layer node is not a layer"); 


	// Get the first layer details record 
	LyrDetails* CurLyrDet = (LyrDetails*)
		(Document::GetCurrent()->GetLayerMgr()).LyrDetList.GetHead(); 
	
	BOOL InvalidateLayersRgn; // Flag used to decide if we should invalidate
							  // a layers region
	BOOL RemoveSelections; 	  // Flag used to indicate if we should remove all
							  // selections from the layer 

    // loop while there are more changes to be made 
	while (CurLyrDet != NULL) 
	{
		InvalidateLayersRgn = FALSE;
		RemoveSelections = FALSE; 

		// We can ignore all new layers which have been deleted 
		if (!((CurLyrDet->New) && (CurLyrDet->Deleted)))
		{
			// Is the layer a new layer ? 
			if (CurLyrDet->New)
			{
				// Attempt to create a new layer node 
				Layer* NewLyr; 
				ALLOC_WITH_FAIL(NewLyr, (new Layer()), this); 	      
				if (NewLyr == NULL)
				{
					goto EndOperation; // We were unable to create a new layer so 
									   // abort the operation 
				}
				// Set the new layer's status  
				NewLyr->SetLayerStatus(CurLyrDet->Status); 
		   
			    // Create a hide node action to hide the new node when we undo/redo
			    HideNodeAction* UndoHideNodeAction; 
			    // ** Change !!!    
				if (!HideNodeAction::Init(this,                    
							 			  &UndoActions,
										  NewLyr, 
										  TRUE, 
							  			  ( Action**)(&UndoHideNodeAction))      
							  			  != AC_FAIL)
				{
					delete NewLyr;     // We won't be needing this 
					goto EndOperation; 		
				}
				// All is well 
				if (CurrentTreeLayer != NULL)
				{
					// Add the new layer to the tree as a previous sibling of 
					// the CurrentTreeLayer 
					NewLyr->AttachNode(CurrentTreeLayer, PREV); 
				}
				else 
				{
					// Add the new layer as a last child of the spread 
					NewLyr->AttachNode(Document::GetCurrent()->
						GetLayerMgr().GetCurrentSpread(), LASTCHILD); 
				}
			}

			// Has the layer been deleted 
			else if (CurLyrDet->Deleted)
			{
				if ( CurLyrDet->Layer == CurrentTreeLayer )
				{
					// We are about to hide the CurrentTreeLayer so we need to find the 
					// next layer before we do this 
					CurrentTreeLayer = ((Layer*)CurrentTreeLayer)->FindNextLayer(); 
				}
				
				// If a layer has been deleted then we ignore all attribute changes 
				// which may have been made prior to the layer being deleted. 
				// Change 
				if (!DoHideNode(CurLyrDet->Layer, 
								TRUE				// Include subtree size 
								)) // Hide the node 
					goto EndOperation; 
				InvalidateLayersRgn = TRUE; // We will need to invalidate the hidden 
											// layers bounding region. 
				RemoveSelections = TRUE;    
			}
			else 
			{
				// Have the attributes of the layer changed 
				if ( !(CurLyrDet->Status == CurLyrDet->Layer->GetLayerStatus()) )	
				{
		
					// Determine if the attribute changes mean that the layer's 
					// bounding rectangle must be invalidated. 
					LayerStatus Old = CurLyrDet->Layer->GetLayerStatus(); 
					LayerStatus New = CurLyrDet->Status; 
					if (
						 (New.Flags.Visible != Old.Flags.Visible) || 
					   	 (New.LayerQualityLevel != Old.LayerQualityLevel)  
					   )  
					{
						InvalidateLayersRgn = TRUE; 
					} 

					// Determine if the attribute changes mean that we should remove
					// the selections on the layer 
					if ( 
						((New.Flags.Visible != Old.Flags.Visible) && 
						 (!New.Flags.Visible)
						) || 
						((New.Flags.Locked != Old.Flags.Locked) && 
						 (New.Flags.Locked)
						)
					   )
					{
						RemoveSelections = TRUE;  
					} 
			
					// Try to create an action to restore the attribute changes we 
					// are about to make 
				   	ChangeLyrAttribAction* UndoAttribChngAction;                          

					if ( ChangeLyrAttribAction::Init(this,                    
									 	      	  &UndoActions,
										      	  sizeof(InvalidateRegionAction),  
												  CurLyrDet->Layer->GetLayerStatus(),
												  CurLyrDet->Layer, 
								 			  	  ( Action**)(&UndoAttribChngAction))
								 			  	  != AC_FAIL) 
					{
						// Change the layer's attributes 
						CurLyrDet->Layer->SetLayerStatus(CurLyrDet->Status); 	
					}
					else 
						goto EndOperation; // We have failed 
			
				}
				// Has the current layers z-position changed ? 
				if (CurLyrDet->Layer != CurrentTreeLayer)
				{
					// I don't think the CurrentTreeLayer can ever be NULL in this situation !
					ENSURE(CurrentTreeLayer != NULL, "The current tree layer is NULL"); 
					// Move the node to its correct tree position 
					// *** Change 
					if(!DoMoveNode(CurLyrDet->Layer, 
						   		   CurrentTreeLayer, 
						    	   PREV 			  // The correct tree position 
								   ))
					{
						goto EndOperation; 
					}				  
				}
				else // The layer is in the correct position in the	tree
				{
					CurrentTreeLayer = ((Layer*)CurrentTreeLayer)->FindNextLayer(); 
				}
			}
			// Do we want to remove the layer's selections 
			if (RemoveSelections)
			{
				NodeRenderableInk::DeselectAllOnLayer(CurLyrDet->Layer); 
			}

			// Do we want to invalidate the bounding rectangle of the layer ? 
			if (InvalidateLayersRgn) 
			{
				DocRect Bounds = CurLyrDet->Layer->GetBoundingRect();
				// Don't bother if the bounding rectangle is empty 
				if (!Bounds.IsEmpty())
				{													  
				 	// Create an InvalidateRegionAction  
					if (!DoInvalidateNodeRegion(CurLyrDet->Layer, FALSE))
					{
						goto EndOperation; 
					}
				}
			}
        }
		// Process the next layer 
		CurLyrDet = (LyrDetails*)
			(Document::GetCurrent()->GetLayerMgr()).LyrDetList.GetNext(CurLyrDet); 
	}
 	EndOperation:
*/
 	End(); 
}
Ejemplo n.º 12
0
void CNetServerTurnManager::NotifyFinishedClientUpdate(int client, const CStrW& playername, u32 turn, const CStr& hash)
{
	// Clients must advance one turn at a time
	ENSURE(turn == m_ClientsSimulated[client] + 1);
	m_ClientsSimulated[client] = turn;

	// Check for OOS only if in sync
	if (m_HasSyncError)
		return;

	m_ClientPlayernames[client] = playername;
	m_ClientStateHashes[turn][client] = hash;

	// Find the newest turn which we know all clients have simulated
	u32 newest = std::numeric_limits<u32>::max();
	for (std::map<int, u32>::iterator it = m_ClientsSimulated.begin(); it != m_ClientsSimulated.end(); ++it)
	{
		if (it->second < newest)
			newest = it->second;
	}

	// For every set of state hashes that all clients have simulated, check for OOS
	for (std::map<u32, std::map<int, std::string> >::iterator it = m_ClientStateHashes.begin(); it != m_ClientStateHashes.end(); ++it)
	{
		if (it->first > newest)
			break;

		// Assume the host is correct (maybe we should choose the most common instead to help debugging)
		std::string expected = it->second.begin()->second;

		// Find all players that are OOS on that turn
		std::vector<CStrW> OOSPlayerNames;
		for (std::map<int, std::string>::iterator cit = it->second.begin(); cit != it->second.end(); ++cit)
		{
			NETTURN_LOG((L"sync check %d: %d = %hs\n", it->first, cit->first, Hexify(cit->second).c_str()));
			if (cit->second != expected)
			{
				// Oh no, out of sync
				m_HasSyncError = true;
				OOSPlayerNames.push_back(m_ClientPlayernames[cit->first]);
			}
		}

		// Tell everyone about it
		if (m_HasSyncError)
		{
			CSyncErrorMessage msg;
			msg.m_Turn = it->first;
			msg.m_HashExpected = expected;
			for (const CStrW& playername : OOSPlayerNames)
			{
				CSyncErrorMessage::S_m_PlayerNames h;
				h.m_Name = playername;
				msg.m_PlayerNames.push_back(h);
			}
			m_NetServer.Broadcast(&msg);
			break;
		}
	}

	// Delete the saved hashes for all turns that we've already verified
	m_ClientStateHashes.erase(m_ClientStateHashes.begin(), m_ClientStateHashes.lower_bound(newest+1));
}
Ejemplo n.º 13
0
void bar(void) {
    ENSURE(1 == 2);
}
Ejemplo n.º 14
0
void foo(void) {
    ENSURE(1 == 1);
}
Ejemplo n.º 15
0
    void test_functional_columns(smt_params fparams, params_ref& params) {
        ast_manager m;
        register_engine re;
        context ctx(m, re, fparams);
        rel_context_base& rctx = *ctx.get_rel_context();
        ctx.updt_params(params);
        relation_manager & rmgr(rctx.get_rmanager());

        sparse_table_plugin & plugin = 
            static_cast<sparse_table_plugin &>(*rctx.get_rmanager().get_table_plugin(symbol("sparse")));
        ENSURE(&plugin);
        table_signature sig2;
        sig2.push_back(2);
        sig2.push_back(2);
        sig2.set_functional_columns(1);
        ENSURE(plugin.can_handle_signature(sig2));
        
        table_fact f00;
        f00.push_back(0);
        f00.push_back(0);
        table_fact f01;
        f01.push_back(0);
        f01.push_back(1);
        table_fact f11;
        f11.push_back(1);
        f11.push_back(1);

        {
            table_aptr t0 = plugin.mk_empty(sig2);
            ENSURE(t0->empty());
            t0->add_fact(f00);
            ENSURE(!t0->empty());
            ENSURE(t0->get_size_estimate_rows()==1);
            t0->add_fact(f01);
            ENSURE(t0->get_size_estimate_rows()==1);
            t0->add_fact(f11);
            ENSURE(t0->get_size_estimate_rows()==2);

            unsigned rem_cols0[]={0};
            scoped_ptr<table_transformer_fn> project0 = rmgr.mk_project_fn(*t0, 1, rem_cols0);
            table_aptr t1 = (*project0)(*t0);
            ENSURE(t1->get_size_estimate_rows()==2);
            ENSURE(t1->get_signature().functional_columns()==0); //project on non-functional column cancels functional

            unsigned rem_cols1[]={1};
            scoped_ptr<table_transformer_fn> project1 = rmgr.mk_project_fn(*t0, 1, rem_cols1);
            table_aptr t2 = (*project1)(*t0);
            ENSURE(t2->get_size_estimate_rows()==2);

            idx_set acc;
            collector_of_reduced * reducer = alloc(collector_of_reduced, acc);
            scoped_ptr<table_transformer_fn> rproject = rmgr.mk_project_with_reduce_fn(*t0, 1, rem_cols0, reducer);
            table_aptr rt = (*rproject)(*t0);
            ENSURE(acc.num_elems()==1);
            ENSURE(rt->get_size_estimate_rows()==1);
        }
        {
            table_aptr t0 = plugin.mk_empty(sig2);
            t0->add_fact(f01);

            unsigned join_cols[]={1};
            scoped_ptr<table_join_fn> join0 = rmgr.mk_join_fn(*t0, *t0, 1, join_cols, join_cols);
            table_aptr t1 = (*join0)(*t0, *t0);
            ENSURE(t1->get_signature().size()==4);
            ENSURE(t1->get_signature().functional_columns()==2);

            table_fact f0011;
            f0011.push_back(0);
            f0011.push_back(0);
            f0011.push_back(1);
            f0011.push_back(1);
            ENSURE(t1->contains_fact(f0011));
            table_fact f0111 = f0011;
            f0111[1] = 1;
            ENSURE(!t1->contains_fact(f0111));
        }

        {
            table_aptr t0 = plugin.mk_empty(sig2);
            t0->display(std::cout<<"0:");
            ENSURE(t0->get_signature().functional_columns()==1);
            
            table_fact aux_fact;

            aux_fact = f01;
            TRUSTME( t0->suggest_fact(aux_fact) );
            t0->display(std::cout<<"1:");
            ENSURE(t0->contains_fact(f01));
            ENSURE(aux_fact[1]==1);

            aux_fact = f00;
            TRUSTME( !t0->suggest_fact(aux_fact) );
            t0->display(std::cout<<"2:");
            ENSURE(t0->contains_fact(f01));
            ENSURE(!t0->contains_fact(f00));
            ENSURE(aux_fact[1]==1);

            t0->ensure_fact(f00);
            t0->display(std::cout<<"3:");
            ENSURE(t0->contains_fact(f00));
            ENSURE(!t0->contains_fact(f01));
        }
    }
Ejemplo n.º 16
0
BOOL CInformErrorDialog::SetupMessage(HDC hDC)
{
	// Set the error message in the text control, and find out the size of the message.
	SIZE TextSize;
	RECT TextRect;
	INT32 Offset = 0;

	CWnd *pMsgCtrl = GetDlgItem(_R(IDC_ERRORBOX_TEXT));
	ENSURE(pMsgCtrl != NULL, "Can't get handle to text control in CInformErrorDialog");

	
	if (pMsgCtrl == NULL)
	{
		// Failed to get at the message control - flag an error
		ENSURE(FALSE, "Unable to access error message control");
		return FALSE;
	}

	// Get rectangle of message control.
	RECT MsgCtrlRect;
	pMsgCtrl->GetWindowRect(&MsgCtrlRect);
	ScreenToClient(&MsgCtrlRect);

	// Use the current control's rectangle as the basis for the formatting rectangle
	// of the text (Bottom will extend in preference to Right)
	TextRect = MsgCtrlRect;

	if (m_StaticTextStr != 0)
	{
		String_256 MsgStr(m_StaticTextStr, m_OwnerModule);
		SetDlgItemText(_R(IDC_ERRORBOX_TEXT), MsgStr);
		DrawText(hDC, (TCHAR *) MsgStr, -1, &TextRect, DT_CALCRECT | DT_TOP | DT_LEFT | DT_WORDBREAK);
	}
	else
	{
		TCHAR *pMsg = Error::GetErrorString();
		SetDlgItemText(_R(IDC_ERRORBOX_TEXT), pMsg);
		DrawText(hDC, pMsg, -1, &TextRect, DT_CALCRECT | DT_TOP | DT_LEFT | DT_WORDBREAK);
	}

	TextSize.cx = TextRect.right - TextRect.left;
	TextSize.cy = TextRect.bottom - TextRect.top;

	if ((TextSize.cx == 0) || (TextSize.cy == 0))
	{
		// Failed to get the size of the text - flag an error
		ENSURE(FALSE, "Unable to read size of error message");
		return FALSE;
	}

	// Get dimensions of message control.
	SIZE MsgCtrlSize;
	MsgCtrlSize.cx = MsgCtrlRect.right - MsgCtrlRect.left;
	MsgCtrlSize.cy = MsgCtrlRect.bottom - MsgCtrlRect.top;

	if ((MsgCtrlSize.cx == 0) || (MsgCtrlSize.cy == 0))
	{
		// Message control has a bad size - flag an error
		ENSURE(FALSE, "Bad message control size in error dialog box!");
		return FALSE;
	}

	// If formatted text is bigger than current control rect
	// we need to resize it...
	if (MsgCtrlSize.cx < TextSize.cx || MsgCtrlSize.cy < TextSize.cy)
	{
		if (MsgCtrlSize.cx < TextSize.cx)
			MsgCtrlSize.cx = TextSize.cx + 8;

		if (MsgCtrlSize.cy < TextSize.cy)
		{
			Offset = TextSize.cy - MsgCtrlSize.cy + 8;
			MsgCtrlSize.cy = TextSize.cy + 8;
		}

		// Resize message.
		if (!pMsgCtrl->SetWindowPos(NULL, 0, 0, MsgCtrlSize.cx, MsgCtrlSize.cy,
		  					   		SWP_NOACTIVATE | SWP_NOZORDER | 
		  					   		SWP_NOMOVE | SWP_NOREDRAW))
		{
			ENSURE(FALSE, "Unable to resize the message control in error box!");
			return FALSE;
		}

		// Move icon (just change IconPos - we ignore the real icon from now on)
		IconPos.y += (Offset / 2);

		// Move buttons
		for (INT32 i = 0; i < ERRORDLG_MAXBUTTONS; i++)
		{
			RECT ButtonRect;
			m_Button[i].GetWindowRect(&ButtonRect);
			ScreenToClient(&ButtonRect);
			if (!m_Button[i].SetWindowPos(NULL, ButtonRect.left, ButtonRect.top + Offset,
										  0, 0,
		  					   		 	  SWP_NOACTIVATE | SWP_NOZORDER | 
		  					   		 	  SWP_NOSIZE | SWP_NOREDRAW))
			{
				ENSURE(FALSE, "Unable to resize the button control in error box!");
				return FALSE;
			}
		}

		// Resize dialog.
		RECT DialogRect;
		GetWindowRect(&DialogRect);
		INT32 DialogWidth  = DialogRect.right  - DialogRect.left;
		INT32 DialogHeight = DialogRect.bottom - DialogRect.top;

		if (!SetWindowPos(NULL, 0, 0, DialogWidth, DialogHeight + Offset,
		  			 	  SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW))
		{
			ENSURE(FALSE, "Unable to resize the error box dialog!");
			return FALSE;
		}
	}

	// All ok!
	return TRUE;
}
Ejemplo n.º 17
0
 const NPb::FieldDescriptor* TProtoSerial::GetFieldDescr(int protoField) {
     const auto* fd = Descr->FindFieldByNumber(protoField);
     ENSURE(fd, "Can't find field number " << protoField << " in message " << Message.GetTypeName());
     return fd;
 }
Ejemplo n.º 18
0
BOOL CInformErrorDialog::OnInitDialog()
{
	CDialog::OnInitDialog();
	
	String_64 BoxTitle;
	BoxTitle = _R(IDS_ERROR_BOX_SERIOUS_ERROR);	// "Serious error"

	String_256 VerySeriousError;
	VerySeriousError = _R(IDS_ERROR_BOX_VERY_SERIOUS_ERROR); // "A very serious error has occured - please consult your technical support."

	// Andy Hills, 22-11-00
	// Store the help context.
	// We need to do this here, because the global help context variable
	// nNextMessageHelpContext may change before the user clicks the 'Help'
	// button. This fixes bug 6359.
	m_nHelpContext = Error::GetErrorNumber();
	if (! m_nHelpContext) m_nHelpContext = GetNextMsgHelpContext();

	// Find out how many buttons there are.
	for (INT32 NumButtons = ERRORDLG_MAXBUTTONS; NumButtons > 0; NumButtons--)
	{
		if (m_ButtonStr[NumButtons - 1] != 0) break;
	}

	// Adjust the OK and Cancel fields if necessary
	if (m_OK > (UINT32) NumButtons)
	{
		if (IsUserName("Tim"))
		{
			TRACE( _T("OK out of range, OK=%u, NumButtons=%d\n"), m_OK, NumButtons);
		}
		// Default to first button
		m_OK = 1;
	}

	if (m_Cancel > (UINT32) NumButtons)
	{
		if (IsUserName("Tim"))
		{
			TRACE( _T("Cancel out of range, Cancel=%u, NumButtons=%d\n"), m_Cancel, NumButtons);
		}

		// Default to be the same as OK (this means a box with a single OK box will
		// respond to Enter and Esc without the user having to specify a Cancel ID).
		m_Cancel = m_OK;
	}

	if (m_Help > (UINT32) NumButtons)
	{
		TRACEUSER( "JustinF", _T("Help button (%d) out of range (%d)\n"),
									(INT32) m_Help, (INT32) NumButtons);
		
		// The only really safe thing we can do is drop the help button.
		m_Help = 0;
	}
		
	// Make sure we have correct dialog information
	GetDialogInfo();
	if (!ValidInfo)
	{
		// Serious error - fall back to to MessageBox().
		goto SevereError;
	}

	// Get icon position
	IconPos = DefIconPos;


	// Get a DC for this dialog, so we can find out the size of text strings.
	// We'll also need to select in our font or else it'll base the width upon the
	// System font rather than the font we're using (MS Sans Serif at last check)
	CDC *pDC;
	CFont *OldFont;

	pDC = GetDC();
	ENSURE(pDC != NULL, "Can't get DC for error box dialog");

	// Check the DC
	if (pDC == NULL)
		goto SevereError;

	OldFont = pDC->SelectObject(GetFont());

	// Set buttons text and move/resize buttons according to the number of them,
	// and their contents.
	BOOL Success;
	Success = SetupButtons(pDC->m_hDC, NumButtons);

	// Size the error message control, and put the message in it.
	Success = Success && SetupMessage(pDC->m_hDC);

	if (OldFont != NULL)
		pDC->SelectObject(OldFont);

	// We've finished with this DC now.
	ReleaseDC(pDC);


	// Check for failure in button/message setup.
	if (!Success)
		goto SevereError;

	// Play the appropriate sound and set the appropriate title bar text ID.
	UINT32 TitleID;
	TitleID = m_TitleStr;
	switch (m_ErrorBoxType)
	{
		case ERRORTYPE_NORMAL:
			// No sound for this one - it's just a message; nothing to shout about.
			if (TitleID == 0) TitleID = _R(IDS_ERRORBOX_NORMAL);
			break;

		case ERRORTYPE_QUESTION:
			MessageBeep(MB_ICONQUESTION);
			if (TitleID == 0) TitleID = _R(IDS_ERRORBOX_NORMAL);
			break;

		case ERRORTYPE_ERROR:
			MessageBeep(MB_ICONEXCLAMATION);
			if (TitleID == 0) TitleID = _R(IDS_ERRORBOX_ERROR);
			break;

		case ERRORTYPE_WARNING:
			MessageBeep(MB_ICONASTERISK);
			if (TitleID == 0) TitleID = _R(IDS_ERRORBOX_WARNING);
			break;

		case ERRORTYPE_SERIOUS:
			MessageBeep(MB_ICONHAND);
			if (TitleID == 0) TitleID = _R(IDS_ERRORBOX_SERIOUS);
			break;

		case ERRORTYPE_ENSURE:
			MessageBeep(MB_ICONHAND);
			if (TitleID == 0) TitleID = _R(IDS_ERRORBOX_ENSURE);
			break;

		default:
			ENSURE(FALSE, "Bad errortype in CInformErrorDialog::OnInitDialog()");
			goto SevereError;
			break;
	}

	// Set the title bar text if necessary.
	if (TitleID != 0)
	{
		String_64 Title(TitleID);
		SetWindowText((TCHAR*) Title);
	}

	// Centre the dialog on the screen (Code stolen from splash.cpp)	
	// Get the size of the screen
	INT32 ScreenWidth, ScreenHeight;
	ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
	ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
	
	// Get the size of the dialog box
	RECT DialogRect;
	GetWindowRect(&DialogRect);
	INT32 DialogWidth, DialogHeight;
	DialogWidth  = DialogRect.right  - DialogRect.left;
	DialogHeight = DialogRect.bottom - DialogRect.top;
	
	// Chicago M7 gives us crap values at this point if we are minimized so try and make them sane
	if (DialogWidth<=0)
		DialogWidth = ScreenWidth / 2;
	else if (DialogWidth > ScreenWidth)
		DialogWidth = ScreenWidth;

	if (DialogHeight<=0)
		DialogHeight = ScreenHeight / 2;
	else if (DialogHeight > ScreenHeight)
		DialogHeight = ScreenHeight;

	// Centre the dialog box and give it the 'top' style.
	INT32 Left, Top;
	Left = (ScreenWidth - DialogWidth) / 2;
	Top  = (ScreenHeight - DialogHeight) / 2;
	SetWindowPos(&wndTop, Left, Top, DialogWidth, DialogHeight, SWP_SHOWWINDOW);
	
	// If we got this far, then we changed the keyboard focus, so return FALSE.
	return FALSE;

SevereError:
	// Ooer - deeply catastrophic error...report to user and exit.
	String_256 Message;

	// First - check that this isn't just because of an empty error message.
	if (m_StaticTextStr == 0)
	{
		// Get the error message
		TCHAR *pMsg = Error::GetErrorString();

		if ((pMsg == NULL) || (pMsg[0] == 0))
		{
			//
			// There is no error message!
			//

			// In debug builds, give developer a chance to go into debugger to see who is not
			// setting an error message.
			#ifdef _DEBUG
			if (::MessageBox(ParentHwnd, 
							 "Somebody reported an error without an error message being set.\r"
							 "Click OK to continue, or Cancel to go into debugger",
							 "DEBUG Warning from Camelot",
							 MB_OKCANCEL| MB_SYSTEMMODAL | MB_ICONHAND) == IDCANCEL)
			{
				// User wants to go into debugger
				DebugBreak();
			}
			#endif

			// Tell the user a spurious error has occured,
			if (!Message.Load(_R(IDS_ERRORBOX_SPURIOUS)))
				// Can't load error message - panic.
				goto VerySevereError;

			// Try to get the string that says "Warning from Camelot"
			String_64 Title;
			if (!Title.Load(_R(IDS_ERRORBOX_WARNING)))
				goto VerySevereError;

			if (::MessageBox(ParentHwnd, (TCHAR *) Message, (TCHAR *) Title,
							 MB_OK | MB_SYSTEMMODAL | MB_ICONHAND) == 0)
				// Could not create the message box - try our fallback one (probably won't
				// work but what the hell).
				goto VerySevereError;

			// Simulate user hitting default button.
			EndDialog((INT32) m_OK);

			return TRUE; // We haven't set the keyboard focus.
		}
	}


	// Inform the user that we've got a bit of a bad karma situation, and that the error
	// box might be not be completely accurate.
	if (!Message.Load(_R(IDS_ERRORBOX_SEVERE)))
		goto VerySevereError;

	if (::MessageBox(ParentHwnd, (TCHAR *) Message, (TCHAR *)BoxTitle, /*"Serious Error", */
					 MB_OK | MB_SYSTEMMODAL | MB_ICONHAND) == 0)
		// Could not create the message box - try our fallback one (probably won't
		// work but what the hell).
		goto VerySevereError;

	// Ok - try to report the error as best we can...

	// Work out what buttons to put on the dialog...

	// We use SYSTEMMODAL with ICONHAND because the SDK docs recommend this for low
	// memory/severe error situations.
	UINT32 MBFlags;
	MBFlags = MB_SYSTEMMODAL | MB_ICONHAND;

	// Do we need a cancel icon?
	if (m_Cancel != m_OK)
		MBFlags |= MB_OKCANCEL;
	else
		MBFlags |= MB_OK;

	if (m_StaticTextStr != 0)
	{
		if (Message.Load(m_StaticTextStr, m_OwnerModule))
		{
			// Error message loaded ok - display it
			INT32 Result =  ::MessageBox(ParentHwnd, (TCHAR *) Message, (TCHAR *)BoxTitle, MBFlags);

			if (Result == 0)
				// Could not create the message box - try our fallback one (probably won't
				// work but what the hell).
				goto VerySevereError;

			if (Result == IDCANCEL)
			{
				// Simulate user hitting cancel button.
				EndDialog((INT32) m_Cancel);
			}
			else
			{
				// Simulate user hitting default button.
				EndDialog((INT32) m_OK);
			}

			return TRUE; // We haven't set the keyboard focus.
		}
		else
		{
			// Can't load error message - bail out
			goto VerySevereError;
		}
	}
	else
	{
		// Get the error message
		TCHAR *pMsg = Error::GetErrorString();

		if (pMsg == NULL)
			// No error message!
			goto VerySevereError;

		// Found error message ok - display it
		INT32 Result =  ::MessageBox(ParentHwnd, pMsg, (TCHAR *)BoxTitle, MBFlags);

		if (Result == 0)
			// Could not create the message box - try our fallback one (probably won't
			// work but what the hell).
			goto VerySevereError;

		if (Result == IDCANCEL)
		{
			// Simulate user hitting cancel button.
			EndDialog((INT32) m_Cancel);
		}
		else
		{
			// Simulate user hitting default button.
			EndDialog((INT32) m_OK);
		}

		return TRUE; // We haven't set the keyboard focus.
	}

VerySevereError:
	// Very bad - we can't even report the error - just let the user that something deeply
	// sad has happened, and pretend that the OK button was pressed.
	::MessageBox(ParentHwnd, (TCHAR *)VerySeriousError,	(TCHAR *)BoxTitle, MB_OK | MB_SYSTEMMODAL | MB_ICONHAND);

	// Simulate user hitting default button.
	EndDialog((INT32) m_OK);

	return TRUE; // We haven't set the keyboard focus.
}
Ejemplo n.º 19
0
BOOL OutputDIB::SetUpBlock( size_t *pBufSize, size_t *pChunkHeight, DIBConvert **pDoConvert,
							FNPTR_SCANLINE *pConvertFn )
{
	BOOL Problems = FALSE;

	switch (SourceBitmapDepth)
	{
		case 32:
		{
			switch (BitmapInfo.biBitCount)
			{
				case 32:
					{
						// real 32-bit BMPs here
						// our 'filter' zeros the transparency bits
						*pConvertFn = DIBUtil::Convert32to32;
						*pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 32 );
					}
					break;
				case 24:
					{
						// convert 32-bit BMPs to 24-bit ones so things can read them
						*pConvertFn = DIBUtil::Convert32to24;	  						// 32->24
						*pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 24 );	// size of 24-bit scanline
					}
					break;
				case 8:
					{
						// 32->8 we do in bigger chunks because of dithering
						*pDoConvert = DIBConvert::Create( SourceBitmapDepth, 8, BitmapInfo.biWidth, OutputPalette, Dither );
						if (*pDoConvert==NULL)
						{
							ENSURE(FALSE, "DIBConvert::Create returned NULL");
							return FALSE;
						}
						*pChunkHeight = 16;
						*pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 8 ) * (*pChunkHeight);
					}
					break;
				case 4:
					{
						// 32->4 we do in bigger chunks because of dithering
						*pDoConvert = DIBConvert::Create( SourceBitmapDepth, 4, BitmapInfo.biWidth, OutputPalette, Dither );
						if (*pDoConvert==NULL)
						{
							ENSURE(FALSE, "DIBConvert::Create returned NULL");
							return FALSE;
						}
						*pChunkHeight = 16;
						*pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 4 ) * (*pChunkHeight);
					}
					break;
				case 1:
					{
						// 32->1 we do in bigger chunks because of dithering
						*pDoConvert = DIBConvert::Create( SourceBitmapDepth, 1, BitmapInfo.biWidth, OutputPalette, Dither );
						if (*pDoConvert==NULL)
						{
							ENSURE(FALSE, "DIBConvert::Create returned NULL");
							return FALSE;
						}
						*pChunkHeight = 16;
						*pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 1 ) * (*pChunkHeight);
					}
					break;
				default:
					Problems = TRUE;
					break;
			}
			break;
		}
		case 8:
			if (BitmapInfo.biBitCount==8)
			{
				// real 8-bit BMPs here
				// we basically just do a memory copy from source to dest
				*pConvertFn = DIBUtil::Convert8to8;
				*pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 8 );
				break;

			}
			Problems = TRUE;
			break;

		default:
			Problems = TRUE;
			break;
	}

	if(Problems)
	{
		Error::SetError( _R(IDE_FORMATNOTSUPPORTED) );
		return FALSE;
	}

	return TRUE;
}
Ejemplo n.º 20
0
bool CNetClientSession::SendMessage(const CNetMessage* message)
{
	ENSURE(m_Host && m_Server);

	return CNetHost::SendMessage(message, m_Server, "server");
}
Ejemplo n.º 21
0
	virtual void Init(const CParamNode& paramNode)
	{
		// The minimum obstruction size is the navcell size * sqrt(2)
		// This is enforced in the schema as a minimum of 1.5
		fixed minObstruction = (Pathfinding::NAVCELL_SIZE.Square() * 2).Sqrt();
		m_TemplateFlags = 0;
		if (paramNode.GetChild("BlockMovement").ToBool())
			m_TemplateFlags |= ICmpObstructionManager::FLAG_BLOCK_MOVEMENT;
		if (paramNode.GetChild("BlockPathfinding").ToBool())
			m_TemplateFlags |= ICmpObstructionManager::FLAG_BLOCK_PATHFINDING;
		if (paramNode.GetChild("BlockFoundation").ToBool())
			m_TemplateFlags |= ICmpObstructionManager::FLAG_BLOCK_FOUNDATION;
		if (paramNode.GetChild("BlockConstruction").ToBool())
			m_TemplateFlags |= ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION;

		m_Flags = m_TemplateFlags;
		if (paramNode.GetChild("DisableBlockMovement").ToBool())
			m_Flags &= (flags_t)(~ICmpObstructionManager::FLAG_BLOCK_MOVEMENT);
		if (paramNode.GetChild("DisableBlockPathfinding").ToBool())
			m_Flags &= (flags_t)(~ICmpObstructionManager::FLAG_BLOCK_PATHFINDING);

		if (paramNode.GetChild("Unit").IsOk())
		{
			m_Type = UNIT;

			CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetEntityHandle());
			if (cmpUnitMotion)
				m_Clearance = cmpUnitMotion->GetUnitClearance();
		}
		else if (paramNode.GetChild("Static").IsOk())
		{
			m_Type = STATIC;
			m_Size0 = paramNode.GetChild("Static").GetChild("@width").ToFixed();
			m_Size1 = paramNode.GetChild("Static").GetChild("@depth").ToFixed();
			ENSURE(m_Size0 > minObstruction);
			ENSURE(m_Size1 > minObstruction);
		}
		else
		{
			m_Type = CLUSTER;
			CFixedVector2D max = CFixedVector2D(fixed::FromInt(0), fixed::FromInt(0));
			CFixedVector2D min = CFixedVector2D(fixed::FromInt(0), fixed::FromInt(0));
			const CParamNode::ChildrenMap& clusterMap = paramNode.GetChild("Obstructions").GetChildren();
			for(CParamNode::ChildrenMap::const_iterator it = clusterMap.begin(); it != clusterMap.end(); ++it)
			{
				Shape b;
				b.size0 = it->second.GetChild("@width").ToFixed();
				b.size1 = it->second.GetChild("@depth").ToFixed();
				ENSURE(b.size0 > minObstruction);
				ENSURE(b.size1 > minObstruction);
				b.dx = it->second.GetChild("@x").ToFixed();
				b.dz = it->second.GetChild("@z").ToFixed();
				b.da = entity_angle_t::FromInt(0);
				b.flags = m_Flags;
				m_Shapes.push_back(b);
				max.X = MAX(max.X, b.dx + b.size0/2);
				max.Y = MAX(max.Y, b.dz + b.size1/2);
				min.X = MIN(min.X, b.dx - b.size0/2);
				min.Y = MIN(min.Y, b.dz - b.size1/2);
			}
			m_Size0 = fixed::FromInt(2).Multiply(MAX(max.X, -min.X));
			m_Size1 = fixed::FromInt(2).Multiply(MAX(max.Y, -min.Y));
		}

		m_Active = paramNode.GetChild("Active").ToBool();
		m_ControlPersist = paramNode.GetChild("ControlPersist").IsOk();

		m_Tag = tag_t();
		if (m_Type == CLUSTER)
			m_ClusterTags.clear();
		m_Moving = false;
		m_ControlGroup = GetEntityId();
		m_ControlGroup2 = INVALID_ENTITY;
	}
Ejemplo n.º 22
0
void CDebugSerializer::Dedent(int spaces)
{
	ENSURE(spaces <= m_Indent);
	m_Indent -= spaces;
}
Ejemplo n.º 23
0
CGUIManager::CGUIManager(ScriptInterface& scriptInterface) :
	m_ScriptInterface(scriptInterface)
{
	ENSURE(ScriptInterface::GetCallbackData(scriptInterface.GetContext()) == NULL);
	scriptInterface.SetCallbackData(this);
}
Ejemplo n.º 24
0
void GUITooltip::ShowTooltip(IGUIObject* obj, CPos pos, const CStr& style, CGUI* gui)
{
	ENSURE(obj);

	// Ignore attempts to use tooltip ""
	if (style.empty())
		return;

	// Get the object referenced by 'tooltip_style'
	IGUIObject* tooltipobj = gui->FindObjectByName("__tooltip_"+style);
	if (! tooltipobj)
	{
		LOGERROR(L"Cannot find tooltip named '%hs'", style.c_str());
		return;
	}

	IGUIObject* usedobj = tooltipobj; // object actually used to display the tooltip in

	CStr usedObjectName;
	if (GUI<CStr>::GetSetting(tooltipobj, "use_object", usedObjectName) == PSRETURN_OK
		&& !usedObjectName.empty())
	{
		usedobj = gui->FindObjectByName(usedObjectName);
		if (! usedobj)
		{
			LOGERROR(L"Cannot find object named '%hs' used by tooltip '%hs'", usedObjectName.c_str(), style.c_str());
			return;
		}

		// Unhide the object. (If it had use_object and hide_object="true",
		// still unhide it, because the used object might be hidden by default)
		GUI<bool>::SetSetting(usedobj, "hidden", false);
	}
	else
	{
		// Unhide the object
		GUI<bool>::SetSetting(usedobj, "hidden", false);

		// Store mouse position inside the CTooltip
		if (GUI<CPos>::SetSetting(usedobj, "_mousepos", pos) != PSRETURN_OK)
			debug_warn(L"Failed to set tooltip mouse position");
	}

	// Retrieve object's 'tooltip' setting
	CStrW text;
	if (m_IsIconTooltip)
	{
		// Use icon tooltip property
		if (GUI<CStrW>::GetSetting(obj, "_icon_tooltip", text) != PSRETURN_OK)
			debug_warn(L"Failed to retrieve icon tooltip text"); // shouldn't fail
	}
	else
	{
		// Use normal tooltip property
		if (GUI<CStrW>::GetSetting(obj, "tooltip", text) != PSRETURN_OK)
			debug_warn(L"Failed to retrieve tooltip text"); // shouldn't fail
	}

	// Do some minimal processing ("\n" -> newline, etc)
	text = text.UnescapeBackslashes();

	// Set tooltip's caption
	if (usedobj->SetSetting("caption", text) != PSRETURN_OK)
		debug_warn(L"Failed to set tooltip caption"); // shouldn't fail

	// Make the tooltip object regenerate its text
	SGUIMessage msg(GUIM_SETTINGS_UPDATED, "caption");
	usedobj->HandleMessage(msg);
}
Ejemplo n.º 25
0
static void tst1() {
  map<char const *, int, str_hash_proc, str_eq_proc> str2int;
  str2int.insert("foo", 35);
  ENSURE(str2int.contains("foo"));
  ENSURE(str2int.find_iterator("foo") != str2int.end());
  ENSURE((*(str2int.find_iterator("foo"))).m_value == 35);
  ENSURE(str2int.size() == 1);
  str2int.insert("boo", 32);
  ENSURE(str2int.contains("foo"));
  ENSURE(str2int.find_iterator("foo") != str2int.end());
  ENSURE((*(str2int.find_iterator("foo"))).m_value == 35);
  ENSURE(str2int.contains("boo"));
  ENSURE(str2int.find_iterator("boo") != str2int.end());
  ENSURE((*(str2int.find_iterator("boo"))).m_value == 32);
  ENSURE(str2int.size() == 2);
  str2int.remove("boo");
  ENSURE(str2int.size() == 1);
  ENSURE(!str2int.contains("boo"));
  ENSURE(str2int.contains("foo"));
}
Ejemplo n.º 26
0
JS::Value ScriptInterface::GetCachedValue(CACHED_VAL valueIdentifier)
{
	std::map<ScriptInterface::CACHED_VAL, JS::PersistentRootedValue>::iterator it = m->m_ScriptValCache.find(valueIdentifier);
	ENSURE(it != m->m_ScriptValCache.end());
	return it->second.get();
}
Ejemplo n.º 27
0
void
_start (void)
{
  // debugging
  /*
  volatile char xxx = 0;
  while (xxx == 0)
    asm volatile ("pause" ::: "memory");
  //*/

  // clear BSS:
  memset (&_section_bss_start[0], 0,
          &_section_bss_end[0] - &_section_bss_start[0]);

  videoram_cls (COLOR_NORMAL);

  // some welcoming information:
  videoram_printf ("\n  Welcome to \e%c chaOS! \n\n", COLOR_ERROR);
  put_cpu_info ();
  put_memory_map ();

  if (!nx_bit_present ())
    {
      videoram_puts (" Your CPU does not support the NX bit! \n", COLOR_ERROR);
      khalt ();
    }

  init_subsystem ("interrupt handling", &interrupts_init, NULL);

  videoram_puts ("Running a syscall test: ", COLOR_NORMAL);
  if (syscall_test ())
    videoram_put_right (" ok ", COLOR_INFO);
  else
    {
      videoram_put_right (" FAIL ", COLOR_ERROR);
      khalt ();
    }

  init_subsystem ("PIC", &pic_init, NULL);
  pit_set_handler (pic_handler_fun);
  pic_mask (~PIC_MASK_PIT);

  videoram_puts ("Setting CPU standards", COLOR_NORMAL);
  cr0_set_reset (CR0_WP|CR0_NE, CR0_MP|CR0_EM|CR0_NE|CR0_AM|CR0_CD|CR0_NW);
  msr_set_reset (MSR_EFER, EFER_NXE, 0);
  videoram_put_right (" ok ", COLOR_INFO);

  init_subsystem ("paging", &paging_init, NULL);

  videoram_puts ("Enabling interrupts", COLOR_NORMAL);
  asm volatile ("sti");
  videoram_put_right (" ok ", COLOR_INFO);

  init_subsystem ("real-time clock", &rtc_init, NULL);
  init_subsystem ("timeout handler", &timeout_init, NULL);
  init_subsystem ("random number generator", &random_init, NULL);
  init_subsystem ("frame allocator", &frame_allocator_init, NULL);

  init_subsystem ("Interrupt timer (33Hz)", &pit_init_33hz, NULL);
  pic_mask (~0);

  init_subsystem ("PS/2 keyboard", &keyboard_init, NULL);
  init_subsystem ("PS/2 mouse", &mouse_init, NULL);

  init_subsystem ("keypress handler", &keypress_handler_init, NULL);
  ENSURE (keypress_handler_set_keymap (KEYMAP_QWERTZ_DE_DE));

  // TODO: initialize more subsystems

  put_welcoming_message ();

  // TODO: do something
  for (;;)
    {
      int c = keypress_handler_getc ();
      if (!c)
        break;
      if (c < 128 && c != 127)
        videoram_printf ("C: <%c>\n", c);
    }
  
  khalt ();
}
Ejemplo n.º 28
0
    void test_finite_product_relation(smt_params fparams, params_ref& params) {
        ast_manager m;
        register_engine re;
        context ctx(m, re, fparams);
        ctx.updt_params(params);
        dl_decl_util dl_util(m);
        relation_manager & rmgr = ctx.get_rel_context()->get_rmanager();

        relation_plugin & rel_plugin = *rmgr.get_relation_plugin(params.get_sym("default_relation", symbol("sparse")));
        ENSURE(&rel_plugin);
        finite_product_relation_plugin plg(rel_plugin, rmgr);

        sort_ref byte_srt_ref(dl_util.mk_sort(symbol("BYTE"), 256), m);
        relation_sort byte_srt = byte_srt_ref;

        relation_signature sig2;
        sig2.push_back(byte_srt);
        sig2.push_back(byte_srt);
        relation_signature sig3(sig2);
        sig3.push_back(byte_srt);
        relation_signature sig4(sig3);
        sig4.push_back(byte_srt);

        app_ref seven_ref(dl_util.mk_numeral(7, byte_srt), m);
        app_ref nine_ref(dl_util.mk_numeral(9, byte_srt), m);

        relation_element seven = seven_ref;
        relation_element nine = nine_ref;

        relation_fact f7(m);
        f7.push_back(seven);
        relation_fact f9(m);
        f9.push_back(nine);

        relation_fact f77(f7);
        f77.push_back(seven);
        relation_fact f79(f7);
        f79.push_back(nine);
        relation_fact f97(f9);
        f97.push_back(seven);
        relation_fact f99(f9);
        f99.push_back(nine);

        relation_fact f779(f77);
        f779.push_back(nine);
        relation_fact f799(f79);
        f799.push_back(nine);
        relation_fact f977(f97);
        f977.push_back(seven);

        relation_fact f7797(f779);
        f7797.push_back(seven);
        relation_fact f7997(f799);
        f7997.push_back(seven);


        bool table_cols2[] = { true, false };
        bool table_cols3[] = { true, false, false };
        bool table_cols4[] = { true, true, false, false };
        scoped_rel<relation_base> r1 = plg.mk_empty(sig2, table_cols2);
        scoped_rel<relation_base> r2 = r1->clone();
        scoped_rel<relation_base> r3 = r2->clone();

        ENSURE(!r1->contains_fact(f77));
        r1->add_fact(f77);
        ENSURE(r1->contains_fact(f77));

        r2->add_fact(f79);
        r3->add_fact(f99);


        r2->display( std::cout << "r2 0\n");
        scoped_rel<relation_base> r4 = r2->clone();
        r2->display( std::cout << "r2 1\n");

        r4->display( std::cout << "r4 0\n");
        ENSURE(!r4->contains_fact(f77));
        ENSURE(r4->contains_fact(f79));
        r4->add_fact(f77);
        r4->display( std::cout << "r4 1\n");
        ENSURE(r4->contains_fact(f77));
        ENSURE(r4->contains_fact(f79));
        r4->add_fact(f99);
        r4->display( std::cout << "r4 2\n");
        ENSURE(r4->contains_fact(f99));


        std::cout << "------ testing union ------\n";
        r2->display( std::cout << "r2\n");
        scoped_ptr<relation_union_fn> union_op = rmgr.mk_union_fn(*r1, *r2, r3.get());
        ENSURE(union_op);
        (*union_op)(*r1, *r2, r3.get());

        r1->display( std::cout << "r1\n");
        r2->display( std::cout << "r2\n");
        r3->display( std::cout << "r3\n");

        ENSURE(r1->contains_fact(f77));
        ENSURE(r1->contains_fact(f79));
        ENSURE(!r1->contains_fact(f99));

        ENSURE(!r3->contains_fact(f77));
        ENSURE(r3->contains_fact(f79));
        ENSURE(r3->contains_fact(f99));

        std::cout << "------ testing join ------\n";

        r1->reset();
        r1->add_fact(f77);
        r1->add_fact(f79);
        r1->add_fact(f97);
        r2->reset();
        r2->add_fact(f97);
        r2->add_fact(f99);

        unsigned col0[] = { 0 };
        unsigned col1[] = { 1 };
        scoped_ptr<relation_join_fn> join_tt = rmgr.mk_join_fn(*r1, *r2, 1, col0, col0);
        scoped_ptr<relation_join_fn> join_tr = rmgr.mk_join_fn(*r1, *r2, 1, col0, col1);
        scoped_ptr<relation_join_fn> join_rr = rmgr.mk_join_fn(*r1, *r2, 1, col1, col1);

        r1->display( std::cout << "r1\n");
        r2->display( std::cout << "r2\n");

        scoped_rel<relation_base> jr_tt = (*join_tt)(*r1, *r2);
        scoped_rel<relation_base> jr_tr = (*join_tr)(*r1, *r2);
        scoped_rel<relation_base> jr_rr = (*join_rr)(*r1, *r2);

        jr_tt->display( std::cout << "tt\n");
        jr_tr->display( std::cout << "tr\n");
        jr_rr->display( std::cout << "rr\n");


        ENSURE(!jr_tt->contains_fact(f7797));
        ENSURE(jr_tr->contains_fact(f7797));
        ENSURE(jr_rr->contains_fact(f7797));


        std::cout << "------ testing project ------\n";

        scoped_rel<relation_base> r31 = plg.mk_empty(sig3, table_cols3);
        r31->add_fact(f779);
        r31->add_fact(f977);
        r31->add_fact(f799);
        
        unsigned rem_1_rel[] = { 1 };
        unsigned rem_2_rel[] = { 1, 2 };
        unsigned rem_1_table[] = { 0 };

        scoped_ptr<relation_transformer_fn> proj_1r = rmgr.mk_project_fn(*r31, 1, rem_1_rel);
        scoped_ptr<relation_transformer_fn> proj_2r = rmgr.mk_project_fn(*r31, 2, rem_2_rel);
        scoped_ptr<relation_transformer_fn> proj_1t = rmgr.mk_project_fn(*r31, 1, rem_1_table);

        scoped_rel<relation_base> sr_1r = (*proj_1r)(*r31);
        scoped_rel<relation_base> sr_2r = (*proj_2r)(*r31);
        scoped_rel<relation_base> sr_1t = (*proj_1t)(*r31);

        ENSURE(sr_1r->contains_fact(f79));
        ENSURE(sr_1r->contains_fact(f97));
        ENSURE(!sr_1r->contains_fact(f77));

        ENSURE(sr_2r->contains_fact(f7));
        ENSURE(sr_2r->contains_fact(f9));

        ENSURE(sr_1t->contains_fact(f79));
        ENSURE(!sr_1t->contains_fact(f97));
        ENSURE(sr_1t->contains_fact(f77));
        ENSURE(sr_1t->contains_fact(f99));

        std::cout << "------ testing filter_interpreted ------\n";

        scoped_rel<relation_base> r41 = plg.mk_empty(sig4, table_cols4);

        r41->add_fact(f7797);
        r41->add_fact(f7997);

        app_ref cond(m.mk_and(
                m.mk_not(m.mk_eq(m.mk_var(1,byte_srt), m.mk_var(2,byte_srt))), //#1!=#2
                m.mk_not(m.mk_eq(m.mk_var(3,byte_srt), m.mk_var(2,byte_srt)))  //#3!=#2
            ), m);
        scoped_ptr<relation_mutator_fn> i_filter = rmgr.mk_filter_interpreted_fn(*r41, cond);
        (*i_filter)(*r41);

        ENSURE(r41->contains_fact(f7797));
        ENSURE(!r41->contains_fact(f7997));

        std::cout << "------ testing filter_by_negation ------\n";

        r31->reset();
        r31->add_fact(f779);
        r31->add_fact(f977);
        r31->add_fact(f799);

        r1->reset();
        r1->add_fact(f77);
        r1->add_fact(f79);

        unsigned nf_r31_cols[] = {1, 0, 1};
        unsigned nf_r1_cols[] = {0, 0, 1};
        scoped_ptr<relation_intersection_filter_fn> neg_filter = rmgr.mk_filter_by_negation_fn(*r31, *r1, 3,
            nf_r31_cols, nf_r1_cols);
        (*neg_filter)(*r31, *r1);

        ENSURE(!r31->contains_fact(f779));
        ENSURE(r31->contains_fact(f977));
        ENSURE(r31->contains_fact(f799));


    }
Ejemplo n.º 29
0
void SimRender::InterpolatePointsRNS(std::vector<CVector2D>& points, bool closed, float offset, int segmentSamples /* = 4 */)
{
	PROFILE("InterpolatePointsRNS");
	ENSURE(segmentSamples > 0);

	std::vector<CVector2D> newPoints;

	// (This does some redundant computations for adjacent vertices,
	// but it's fairly fast (<1ms typically) so we don't worry about it yet)

	// TODO: Instead of doing a fixed number of line segments between each
	// control point, it should probably be somewhat adaptive to get a nicer
	// curve with fewer points

	size_t n = points.size();

	if (closed)
	{
		if (n < 1)
			return; // we need at least a single point to not crash
	}
	else
	{
		if (n < 2)
			return; // in non-closed mode, we need at least n=2 to not crash
	}

	size_t imax = closed ? n : n-1;
	newPoints.reserve(imax*segmentSamples);

	// these are primarily used inside the loop, but for open paths we need them outside the loop once to compute the last point
	CVector2D a0;
	CVector2D a1;
	CVector2D a2;
	CVector2D a3;

	for (size_t i = 0; i < imax; ++i)
	{
		// Get the relevant points for this spline segment; each step interpolates the segment between p1 and p2; p0 and p3 are the points
		// before p1 and after p2, respectively; they're needed to compute tangents and whatnot.
		CVector2D p0; // normally points[(i-1+n)%n], but it's a bit more complicated due to open/closed paths -- see below
		CVector2D p1 = points[i];
		CVector2D p2 = points[(i+1)%n];
		CVector2D p3; // normally points[(i+2)%n], but it's a bit more complicated due to open/closed paths -- see below

		if (!closed && (i == 0))
			// p0's point index is out of bounds, and we can't wrap around because we're in non-closed mode -- create an artificial point
			// that extends p1 -> p0 (i.e. the first segment's direction)
			p0 = points[0] + (points[0] - points[1]);
		else
			// standard wrap-around case
			p0 = points[(i-1+n)%n]; // careful; don't use (i-1)%n here, as the result is machine-dependent for negative operands (e.g. if i==0, the result could be either -1 or n-1)


		if (!closed && (i == n-2))
			// p3's point index is out of bounds; create an artificial point that extends p_(n-2) -> p_(n-1) (i.e. the last segment's direction)
			// (note that p2's index should not be out of bounds, because in non-closed mode imax is reduced by 1)
			p3 = points[n-1] + (points[n-1] - points[n-2]);
		else
			// standard wrap-around case
			p3 = points[(i+2)%n];


		// Do the RNS computation (based on GPG4 "Nonuniform Splines")
		float l1 = (p2 - p1).Length(); // length of spline segment (i)..(i+1)
		CVector2D s0 = (p1 - p0).Normalized(); // unit vector of spline segment (i-1)..(i)
		CVector2D s1 = (p2 - p1).Normalized(); // unit vector of spline segment (i)..(i+1)
		CVector2D s2 = (p3 - p2).Normalized(); // unit vector of spline segment (i+1)..(i+2)
		CVector2D v1 = (s0 + s1).Normalized() * l1; // spline velocity at i
		CVector2D v2 = (s1 + s2).Normalized() * l1; // spline velocity at i+1

		// Compute standard cubic spline parameters
		a0 = p1*2 + p2*-2 + v1 + v2;
		a1 = p1*-3 + p2*3 + v1*-2 + v2*-1;
		a2 = v1;
		a3 = p1;

		// Interpolate at regular points across the interval
		for (int sample = 0; sample < segmentSamples; sample++)
			newPoints.push_back(EvaluateSpline(sample/((float) segmentSamples), a0, a1, a2, a3, offset));

	}

	if (!closed)
		// if the path is open, we should take care to include the last control point
		// NOTE: we can't just do push_back(points[n-1]) here because that ignores the offset
		newPoints.push_back(EvaluateSpline(1.f, a0, a1, a2, a3, offset));

	points.swap(newPoints);
}
Ejemplo n.º 30
0
	virtual u16 GetTilesPerSide()
	{
		ssize_t tiles = m_Terrain->GetTilesPerSide();
		ENSURE(1 <= tiles && tiles <= 65535);
		return (u16)tiles;
	}